Vb.net 如何将从一个项目加载的类型转换为接口

Vb.net 如何将从一个项目加载的类型转换为接口,vb.net,reflection,Vb.net,Reflection,先决条件 .NET环境 带有接口的IModule的Common程序集 Mainproject,参考Common Implementorproject,参考Common,但未参考Main 构建所有内容时,Common.dll同时出现在Main和Implementor中 现在,Main项目尝试在运行时加载实现IModule的类。到目前为止我所能取得的成就: Dim asm = Assembly.LoadFrom(asmFile) For Each asmType in asm.GetExport

先决条件

  • .NET环境
  • 带有接口的
    IModule的
    Common
    程序集
  • Main
    project,参考
    Common
  • Implementor
    project,参考
    Common
    ,但未参考
    Main
    构建所有内容时,
    Common.dll
    同时出现在
    Main
    Implementor
现在,
Main
项目尝试在运行时加载实现
IModule
的类。到目前为止我所能取得的成就:

Dim asm = Assembly.LoadFrom(asmFile)
For Each asmType in asm.GetExportedTypes()
    If asmType.IsClass AndAlso
       asmType.GetInterfaces().Any(Function(i) i.Name = GetType(IModule).Name) Then
        Dim handle = AppDomain.CurrentDomain.CreateInstanceFrom(asmFile, asmType.FullName)
        Dim inst = CType(handle.Unwrap(), IModule) ' EXCEPTION
    End If
Next
因此,我可以加载
实现器
程序集,并找到实现
IModule
的类型。但我无法创建它的实例,以便将其强制转换到本地的
IModule
。这有可能吗

变通办法

我找到了一个解决方法-在
实现者
项目中,单击对
通用
的引用并清除“复制本地”标志。然后我甚至可以使用更简单的代码,比如
IsAssignableFrom()
。但这是唯一的办法吗?如果我从第三方获得了一个DLL,其中编译了
IModule
,该怎么办?

EDIT
Assembly.LoadFrom
加载目录树中找到的第一个匹配程序集(通过所谓的。因此,如果您有
Common
DLLin文件夹A,并且更新后的
Common
DLL位于文件夹A\B中,则采用文件夹A中的一个(如果两个DLL具有相同的名称)

发件人:

“从上下文加载”允许从路径加载程序集 包括在探测中,但允许对该路径的依赖关系 已找到并加载,因为路径信息由 上下文

加载方法有以下缺点:考虑使用 改为加载

If an assembly with the same identity is already loaded, LoadFrom returns the loaded assembly even if a different path was specified.

If an assembly is loaded with LoadFrom, and later an assembly in the load context attempts to load the same assembly by display name,
加载尝试失败。在加载程序集时可能会发生这种情况 反序列化

If an assembly is loaded with LoadFrom, and the probing path includes an assembly with the same identity but a different location,
InvalidCastException、MissingMethodException或其他意外异常 行为可能发生


原始答复:

使用
Activator.CreateInstance
创建对象,并使用
typeof
检查它是否实现了接口:

Dim a As assembly = Assembly.LoadFrom(asmFile)
Dim concreteModule As IModule = Nothing
For each type In a.GetExportedTypes().Where(Function(x) x.IsClass)
    Dim o  = Activator.CreateInstance(type)
    If TypeOf o Is IModule
       concreteModule = DirectCast(o, IModule)
       Exit For
    End If          
Next 
备注:

您写道:
但我无法创建它的实例,以便将其强制转换到本地IModule

具体对象必须实现您强制转换到的接口。我不知道我是否理解正确,但是从第三方dll中的接口
IModule
转换到本地dll中的不同接口
IModule*
将不起作用(除非您的本地接口实现了其他接口)。

编辑
Assembly.LoadFrom
加载目录树中找到的第一个匹配程序集(通过所谓的。因此,如果您有
Common
DLLin文件夹A,并且更新后的
Common
DLL位于文件夹A\B中,则采用文件夹A中的一个(如果两个DLL具有相同的名称)

发件人:

“从上下文加载”允许从路径加载程序集 包括在探测中,但允许对该路径的依赖关系 已找到并加载,因为路径信息由 上下文

加载方法有以下缺点:考虑使用 改为加载

If an assembly with the same identity is already loaded, LoadFrom returns the loaded assembly even if a different path was specified.

If an assembly is loaded with LoadFrom, and later an assembly in the load context attempts to load the same assembly by display name,
加载尝试失败。在加载程序集时可能会发生这种情况 反序列化

If an assembly is loaded with LoadFrom, and the probing path includes an assembly with the same identity but a different location,
InvalidCastException、MissingMethodException或其他意外异常 行为可能发生


原始答复:

使用
Activator.CreateInstance
创建对象,并使用
typeof
检查它是否实现了接口:

Dim a As assembly = Assembly.LoadFrom(asmFile)
Dim concreteModule As IModule = Nothing
For each type In a.GetExportedTypes().Where(Function(x) x.IsClass)
    Dim o  = Activator.CreateInstance(type)
    If TypeOf o Is IModule
       concreteModule = DirectCast(o, IModule)
       Exit For
    End If          
Next 
备注:

您写道:
但我无法创建它的实例,以便将其强制转换到本地IModule


具体对象必须实现您强制转换到的接口。我不知道我是否理解正确,但是从第三方dll中的接口
IModule
转换到本地dll中的不同接口
IModule*
将不起作用(除非您的本地接口实现了另一个).

从第三方dll中的接口IModule强制转换到本地dll中的不同接口IModule*
-这正是我想要做的。我将一个带有
IModule
的DLL交给第三方,并(至少)取回两个DLL—一个带有
IModule
,另一个带有
implementor
。它们被放置在一个单独的目录中,并从那里加载。但在加载时,会获取
IModule
DLL的本地副本,而在我尝试强制转换时,会使用main
IModule
(使用
main
项目编译的副本)。我可以在这两者之间进行转换吗?我可能找到了一个部分解决方法-使用
reflectiononnlyloadfrom
并通过加载我的
Main
DLL对“缺少DLL”事件作出反应。我还没有试过,但这在检查类型时应该会起作用。但是当实例化时,我假设只有
反射
加载是不够的,所以我又遇到了同样的情况。好吧,我想我明白了。修改后的第三方DLL复制到的目录是主项目的子目录吗?如果是,你能改变吗?Imho.NET加载在目录树中找到的第一个匹配程序集。是的,它是一个子目录,我可以将其更改为什么?主dll
之外的任何文件夹从第三方dll中的接口IModule强制转换到本地dll中的不同接口IModule*
-这正是我想要做的。我将一个带有
IModule
的DLL交给第三方,并(至少)取回两个DLL—一个带有
IModule
,另一个带有
implementor
。它们被放置在一个单独的目录中,并从那里加载。但在加载时,会获取
IModule
DLL的本地副本,而在我尝试强制转换时,会使用main
IModule
(使用
main
项目编译的副本)。我能在这两者之间转换吗