2010-07-30 76 views
1

在我的应用程序中,我想加载驻留在网络共享上的程序集(应用程序本身也在该共享上),而无需将它们添加到项目的输出路径中。我想要的是一个输出目录,除了应用程序之外什么都没有。在.Net应用程序中引用程序集

仅仅将目标目录添加到我的项目的参考路径将不起作用。

我尝试设置在App.config探测目录,但没有奏效提前(甚至测试它在我的本地diks而不是网络共享)

感谢任何提示!

编辑:似乎这是通过反思的方式。没有更好的方式使用像NInject这样的依赖注入容器吗?

+0

在大多数情况下,让输出路径中的所有程序集都不像第一眼那样糟糕。那么,为什么你认为你需要以不同的方式做呢? – 2010-07-30 11:12:02

+0

基本上你是对的 - 不伤害他们不会让他们在那里。但是我们有一个接近12个前端的地方,它使用1.2.x版本中的一个库,另外三个需要1.2.y(或者任何其他版本,只是给出随机数)。因此,我们正在从这些库中提取接口(以嵌入到项目中)并从应用程序中删除实现程序集(将它们放到网络上以动态加载)。这种方法的优点是,当需要库的错误修正时,我们甚至不必重新编译我们的应用程序 - 界面保持不变。 – 2010-08-02 06:22:59

+0

Ninject不会给你任何你不能通过代码做的事情。为了使用Ninject(和其他DI容器),您必须能够以某种方式加载程序集。 – 2010-08-02 07:27:16

回答

2

不幸的是,你不能添加一个任意目录到你的探测路径:只有你的应用程序中的一个子目录。

但是,可以使用<assemblyBinding>中的<codeBase>元素提供组件的完整路径。 MSDN page for <assemblyBinding>上有一个例子。缺点是你需要明确列出你的应用程序引用的所有程序集的路径。

另一种选择是在运行时通过Assembly.LoadFrom加载程序集并通过反射调用方法。如果沿着这条路线走,你必须阅读Suzanne Cook's blog。如果你什么也没读,请阅读Choosing a Binding Context

2

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

Assembly myAssembly = Assembly.LoadFrom(assemblyPath); 

请注意,您还需要加载任何相关程序集。 一旦你有了这个,你可以使用的对象创建:

object myObject = myAssembly.CreateInstance(typeName); 

并将其强制通过的typeName

0

如果我理解正确的话,你想从一个程序集加载类指定的类型,而不必引用大会的项目?

然后,你可以使用这个类来获得一个实现/继承某一类型的所有类型:

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 

之后,用约翰Sibly的回答对飞创建任何类型的对象

干杯!

相关问题