在 .Net 应用程序中引用程序集

发布于 2024-09-11 23:46:02 字数 289 浏览 10 评论 0原文

在我的应用程序中,我想加载驻留在网络共享上的程序集(应用程序本身也位于该共享上),而不必将它们添加到项目的输出路径中。我想要的是一个除了应用程序之外几乎不包含任何内容的输出目录。

仅将目标目录添加到我的项目的引用路径中是行不通的。

我尝试在 App.Config 中设置探测目录,但这不起作用(甚至在我的本地磁盘而不是网络共享上测试了它)

提前感谢您的任何提示!

编辑:似乎这种情况是通过反思来引导的。是否有更优雅的方式使用像 NInject 这样的依赖注入容器?

In my application, I would like to load Assemblies that reside on a network share (The application itself is on that share, too) without having to add them to the project's output path. What I'd like to have is an output directory that contains next to nothing but the application.

Merely adding the target directory to my project's reference path's won't work.

I tried setting the probing directory in the App.Config, but that didn't work (even tested it on my local diks instead of the network share)

Thanks in advance for any hints!

EDIT : Seems the way this is going leads through reflection. Isn't there a more elegant way using Dependency Injection containers like NInject?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

千紇 2024-09-18 23:46:02

不幸的是,您无法将任意目录添加到探测路径:只能是应用程序中的子目录。

但是,可以使用 中的 元素提供程序集的完整路径。有一个例子 的 MSDN 页面。缺点是您需要显式列出应用程序引用的所有程序集的路径。

另一种选择是在运行时通过 Assembly.LoadFrom 加载程序集并通过反射调用方法。如果您沿着这条路线走下去,则必须阅读 Suzanne Cook 的博客 。如果您没有阅读其他内容,请阅读 选择绑定上下文

Unfortunately you can't add an arbitrary directory to your probing path: only a subdirectory within your application.

However, it's possible to provide full paths to assemblies using the <codeBase> element within an <assemblyBinding>. There's an example on the MSDN page for <assemblyBinding>. The downside is that you'll need to explicitly list paths for all the assemblies your application references.

Another option is to load assemblies at run time through Assembly.LoadFrom and invoke methods through reflection. If you go down this route, you must read Suzanne Cook's blog. If you read nothing else, read Choosing a Binding Context.

征﹌骨岁月お 2024-09-18 23:46:02

我会看一下 Assembly.LoadFrom。您可以编写如下代码:

Assembly myAssembly = Assembly.LoadFrom(assemblyPath);

请注意,您还需要加载任何依赖程序集。
一旦你有了这个,你就可以使用以下方法创建对象:

object myObject = myAssembly.CreateInstance(typeName);

并将其转换为 typeName 指定的类型

I'd take a look at Assembly.LoadFrom. You be able to write some code like this:

Assembly myAssembly = Assembly.LoadFrom(assemblyPath);

Note that you'll also need to load any dependant assemblies as well.
Once you have this you can create as object using:

object myObject = myAssembly.CreateInstance(typeName);

And cast it to the type specified by typeName

情归归情 2024-09-18 23:46:02

如果我理解正确,您想从程序集中加载类而不必引用程序集的项目吗?

然后,您可以使用此类来获取实现/继承特定类型的所有类型:

Imports System.IO
Imports System.Threading
Imports Exceptions
Imports System.Reflection
Imports ModuleInterfaces

Public Class StartupLoader
    Private ReadOnly syncroot As New Object

    Private _handler As ExceptionHandler ' custom class to handle exceptions'
    Private _typeToLoad As Type

    Public Sub New(ByVal typeToLoad As Type, _
                   ByVal handler As ExceptionHandler)
        _handler = handler
        _typeToLoad = typeToLoad
    End Sub

    Public Function LoadDLLs() As List(Of Type)
        Dim threads As New List(Of Thread)
        Dim types As New List(Of Type)
        Dim exceptions As New List(Of Exception)
        Dim folders As New Stack(Of String)
        Dim t As Thread

        folders.Push(Directory.GetCurrentDirectory) ' change to your dir here, could use a member var'
        While Not folders.Count = 0
            For Each f In Directory.GetFiles(folders.Peek)
                Dim tmp As String = f
                If tmp.ToLower.EndsWith(".dll") OrElse _
                   tmp.ToLower.EndsWith(".exe") Then
                    t = New Thread(AddressOf LoadDLLsThread)

                    t.Start(New Object() {tmp, types, exceptions})
                    threads.Add(t)
                End If
            Next

            For Each d In Directory.GetDirectories(folders.Peek)
                folders.Push(d)
            Next

            folders.Pop()
        End While

        For Each t In threads
            t.Join()
        Next

        If exceptions.Count > 0 Then
            Throw New ThreadedException(exceptions) ' Custom exception containing a List(Of Exception)'
        End If

        Return types

    End Function

    Private Sub LoadDLLsThread(ByVal vObj As Object)
        Dim objs As Object() = CType(vObj, Object())
        Dim fileName As String = CStr(objs(0))
        Dim globalTypes As List(Of Type) = CType(objs(1), Global.System.Collections.Generic.List(Of Global.System.Type))
        Dim exceptions As List(Of Exception) = CType(objs(2), Global.System.Collections.Generic.List(Of Global.System.Exception))

        Dim types As New List(Of Type)

        Try
            Dim myAssembly As Assembly = Assembly.LoadFrom(fileName)

            For Each t In myAssembly.GetTypes()
                If _typeToLoad.IsAssignableFrom(t) AndAlso _
                   t.IsClass = True AndAlso _
                   t.IsAbstract = False Then
                    types.Add(t)
                End If
            Next

            SyncLock syncroot
                globalTypes.AddRange(types)
            End SyncLock

        Catch ex As Exception
            SyncLock syncroot
                exceptions.Add(ex)
            End SyncLock
        End Try

    End Sub

End Class

之后,使用 John Sible 的答案来创建任何类型的对象即时

干杯!

If I understand correctly, you want to load classes from an assembly without having to reference the assembly's project ?

Then you could use this class to get all types that implements / inherits a certain type :

Imports System.IO
Imports System.Threading
Imports Exceptions
Imports System.Reflection
Imports ModuleInterfaces

Public Class StartupLoader
    Private ReadOnly syncroot As New Object

    Private _handler As ExceptionHandler ' custom class to handle exceptions'
    Private _typeToLoad As Type

    Public Sub New(ByVal typeToLoad As Type, _
                   ByVal handler As ExceptionHandler)
        _handler = handler
        _typeToLoad = typeToLoad
    End Sub

    Public Function LoadDLLs() As List(Of Type)
        Dim threads As New List(Of Thread)
        Dim types As New List(Of Type)
        Dim exceptions As New List(Of Exception)
        Dim folders As New Stack(Of String)
        Dim t As Thread

        folders.Push(Directory.GetCurrentDirectory) ' change to your dir here, could use a member var'
        While Not folders.Count = 0
            For Each f In Directory.GetFiles(folders.Peek)
                Dim tmp As String = f
                If tmp.ToLower.EndsWith(".dll") OrElse _
                   tmp.ToLower.EndsWith(".exe") Then
                    t = New Thread(AddressOf LoadDLLsThread)

                    t.Start(New Object() {tmp, types, exceptions})
                    threads.Add(t)
                End If
            Next

            For Each d In Directory.GetDirectories(folders.Peek)
                folders.Push(d)
            Next

            folders.Pop()
        End While

        For Each t In threads
            t.Join()
        Next

        If exceptions.Count > 0 Then
            Throw New ThreadedException(exceptions) ' Custom exception containing a List(Of Exception)'
        End If

        Return types

    End Function

    Private Sub LoadDLLsThread(ByVal vObj As Object)
        Dim objs As Object() = CType(vObj, Object())
        Dim fileName As String = CStr(objs(0))
        Dim globalTypes As List(Of Type) = CType(objs(1), Global.System.Collections.Generic.List(Of Global.System.Type))
        Dim exceptions As List(Of Exception) = CType(objs(2), Global.System.Collections.Generic.List(Of Global.System.Exception))

        Dim types As New List(Of Type)

        Try
            Dim myAssembly As Assembly = Assembly.LoadFrom(fileName)

            For Each t In myAssembly.GetTypes()
                If _typeToLoad.IsAssignableFrom(t) AndAlso _
                   t.IsClass = True AndAlso _
                   t.IsAbstract = False Then
                    types.Add(t)
                End If
            Next

            SyncLock syncroot
                globalTypes.AddRange(types)
            End SyncLock

        Catch ex As Exception
            SyncLock syncroot
                exceptions.Add(ex)
            End SyncLock
        End Try

    End Sub

End Class

After that, use John Sibly's answer to create an object of any of the types on the fly

Cheers !

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文