将DLL加载到不同的AppDomain及其依赖项中



我在不同的AppDomain中通过反射加载DLL时遇到了一点麻烦。

这是我的场景。

  1. 我有一个名为Interfaces.DLL的DLL,它只包含一个接口定义。
  2. Test.DLL包含了Interfaces.DLL,并定义了一个叫做Connector的类,它实现了在之前的dll中定义的接口。
  3. 我有一个应用程序,其中只包括接口。dll,需要使用反射加载Test.dll
  4. 我调用类连接器的公共方法,它返回我通过反射加载的DLL文件的DLL版本。之后,我调用一个web服务来检查我是否有文件的更高版本。如果没有,我必须卸载dll,删除文件,然后下载新文件。

问题在步骤3。当我尝试在不同的AppDomain中加载Test.DLL时,我得到一个错误,因为它无法在AppDomain中找到Interfaces.Dll。消息是:

System.IO.FileNotFoundException was unhandled
 FileName=BankInterfaces, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null

那么,我如何在AppDomain中加载2个不同的Dll ?

这是我的代码:

Interface.DLL

Public Interface BankInterface
       Function getDLLVersion() As Double
       'Other methods here
End Interface

Test.DLL

Public Class Connector
    Implements BankInterfaces.BankInterface
    Public Function getDLLVersion() As Double Implements BankInterfaces.BankInterface.getDLLVersion
         Return 2.5
    End Function

MainApplication

Public Sub Main()
    Dim domainSetup As New AppDomainSetup
    domainSetup.ApplicationName = appDomainName
    domainSetup.ApplicationBase = "C:Usersjferrer.GLOBALAppDataRoamingEnterpriseAppNameDllFiles"
    Dim LocalAppDomain As AppDomain = AppDomain.CreateDomain("BankDLL" & Guid.NewGuid.ToString.GetHashCode.ToString("x"), Nothing, domainSetup)
    AddHandler AppDomain.CurrentDomain.AssemblyResolve, AddressOf CurrentDomain_AssemblyResolve
    LocalAppDomain.CreateInstanceFrom("C:Usersjferrer.GLOBALAppDataRoamingEnterpriseAppNameDllFilesTestDLL.dll", "TestDLL.Connector") 'This line throw the error
    Dim conector As Type = LocalAppDomain.GetType()
    'Irrelevant code here
end sub
Private Function CurrentDomain_AssemblyResolve(ByVal sender As Object, ByVal args As ResolveEventArgs) As Assembly
    Try
        Dim myassembly As Assembly = Assembly.Load(args.Name)
        If Not IsNothing(myassembly) Then
            Return myassembly
        End If
    Catch ex As Exception
    End Try
    Dim parts As String() = args.Name.Split(",")
    Dim myfile As String = "C:Usersjferrer.GLOBALAppDataRoamingEnterpriseAppNameDllFiles" & parts(0).Trim() & ".dll"
    Return Assembly.LoadFrom(myfile)
end function
更新:

如果我改变

AddHandler AppDomain.CurrentDomain.AssemblyResolve, AddressOf CurrentDomain_AssemblyResolve 

AddHandler LocalAppDomain.CurrentDomain.AssemblyResolve, AddressOf CurrentDomain_AssemblyResolve

我从Visual Studio得到一个警告:

Warning 1   Access of shared member, constant member, enum member or nested type through an instance; qualifying expression will not be evaluated.  C:ProyectosBANKBankTestForm1.vb 49  20  BankTest

和原来的行为没有区别

尽管我没有直接应用@James Barras的建议,但他的评论帮助我找到了这个解决方案。所以,谢谢你花时间帮助我:)

这是一个可能的解决方案,任何人在我的情况:

  1. 你想要反序列化的类必须继承MarshalByRefObject
  2. 类中方法返回的对象必须是可序列化的
  3. 创建这个类:

    Imports System.Reflection
    Public Class Loader
    Inherits MarshalByRefObject
    Private Function CallInternal(dll As String, typename As String, method As String, parameters As Object()) As Object
        Dim a As Assembly = Assembly.LoadFile(dll)
        Dim o As Object = a.CreateInstance(typename)
        Dim t As Type = o.[GetType]()
        Dim m As MethodInfo = t.GetMethod(method)
        Return m.Invoke(o, parameters)
    End Function
    Public Shared Function [Call](dll As String, typename As String, method As String, ParamArray parameters As Object()) As Object
        Dim dom As AppDomain = AppDomain.CreateDomain("MyNewDomain")
        Dim ld As Loader = DirectCast(dom.CreateInstanceAndUnwrap(Assembly.GetExecutingAssembly().FullName, GetType(Loader).FullName), Loader)
        Dim result As Object = ld.CallInternal(dll, typename, method, parameters)
        AppDomain.Unload(dom)
        Return result
    End Function
    End Class
    
  4. 使用下面的代码在你想加载的dll中调用一个方法:

    Loader.Call(pathToDLL, ClasName,MethodName, parameters)
    

此解决方案在调用任何方法后卸载域。所以它不是完美的,因为如果你想调用几个方法,你将在执行时间上受到惩罚。

相关内容

  • 没有找到相关文章

最新更新