Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/postgresql/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.net 将DLL加载到不同的AppDomain及其依赖项中_.net_Vb.net_Reflection_Appdomain - Fatal编程技术网

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

.net 将DLL加载到不同的AppDomain及其依赖项中,.net,vb.net,reflection,appdomain,.net,Vb.net,Reflection,Appdomain,我在不同的AppDomain中通过反射加载DLL时遇到了一些问题 这是我的设想 我有一个名为Interfaces.DLL的DLL,它只包含一个接口定义 Test.DLL包含Interfaces.DLL并定义一个名为Connector的类,该类实现在以前的DLL上定义的接口 我有一个只包含Interfaces.dll的应用程序,需要使用反射加载Test.dll 我调用类连接器的一个公共方法,该方法返回反射加载的DLL文件的DLL版本。之后,我调用一个web服务来检查是否有更高版本的文件。如果没有,

我在不同的AppDomain中通过反射加载DLL时遇到了一些问题

这是我的设想

  • 我有一个名为Interfaces.DLL的DLL,它只包含一个接口定义
  • Test.DLL包含Interfaces.DLL并定义一个名为Connector的类,该类实现在以前的DLL上定义的接口
  • 我有一个只包含Interfaces.dll的应用程序,需要使用反射加载Test.dll
  • 我调用类连接器的一个公共方法,该方法返回反射加载的DLL文件的DLL版本。之后,我调用一个web服务来检查是否有更高版本的文件。如果没有,我必须卸载dll,删除文件,然后下载新文件
  • 问题出在第三步。当我尝试在另一个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

    这是我的代码:

    接口.DLL

    Public Interface BankInterface
           Function getDLLVersion() As Double
           'Other methods here
    End Interface
    
    Public Class Connector
        Implements BankInterfaces.BankInterface
        Public Function getDLLVersion() As Double Implements BankInterfaces.BankInterface.getDLLVersion
             Return 2.5
        End Function
    
    Test.DLL

    Public Interface BankInterface
           Function getDLLVersion() As Double
           'Other methods here
    End Interface
    
    Public Class Connector
        Implements BankInterfaces.BankInterface
        Public Function getDLLVersion() As Double Implements BankInterfaces.BankInterface.getDLLVersion
             Return 2.5
        End Function
    
    main应用程序

    Public Sub Main()
        Dim domainSetup As New AppDomainSetup
        domainSetup.ApplicationName = appDomainName
        domainSetup.ApplicationBase = "C:\Users\jferrer.GLOBAL\AppData\Roaming\Enterprise\AppName\DllFiles\"
    
        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:\Users\jferrer.GLOBAL\AppData\Roaming\Enterprise\AppName\DllFiles\TestDLL.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:\Users\jferrer.GLOBAL\AppData\Roaming\Enterprise\AppName\DllFiles\" & parts(0).Trim() & ".dll"
    
        Return Assembly.LoadFrom(myfile)
    end function
    
    更新:

    如果我改变

    AddHandler AppDomain.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:\Proyectos\BANK\BankTest\Form1.vb 49  20  BankTest
    

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

    这对我这种情况下的任何人来说都是可行的解决方案:

  • 要反序列化的类必须从MarshalByRefObject继承
  • 类中的方法返回的对象必须是可序列化的
  • 创建此类:

    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
    
  • 使用以下代码调用要加载的dll内的方法:

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

  • 此解决方案在您调用任何方法后卸载域。因此它并不完美,因为如果您想调用多个方法,您将在执行时间上受到惩罚。

    AssemblyResolve不应该在LocalAppDomain上吗?这不是必需的。AssemblyResolved是共享成员:我知道什么是共享成员。不是。您想要
    LocalAppDomain.AssemblyResolve
    而不是
    LocalAppDomain.CurrentDomain.AssemblyResolve
    程序集解析事件在BankTest中,因此需要加载该事件以连接程序集解析事件,但您移动了应用程序库。所以它找不到它