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

时间:2016-07-04 08:53:01

标签: vb.net reflection

先决条件

  • .NET环境
  • 具有接口Common
  • IModule程序集
  • Main项目,引用Common
  • Implementor项目,引用Common,但未引用Main 构建完所有内容后,Common.dllMain中都会显示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

所以我可以加载Implementor程序集并找到实现IModule的类型。但是我无法创建它的实例,以便我可以将它投射到我的本地IModule。这有可能吗?

解决方法

我找到了一种解决方法 - 在Implementor项目中,点击对Common的引用并清除"复制本地"旗。然后我甚至可以使用更简单的代码,比如IsAssignableFrom()。但这是唯一的方法吗?如果我从第三方获取DLL,IModule被编译到其中会怎么样?

1 个答案:

答案 0 :(得分:0)

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

来自MSDN

  

load-from上下文允许从不是路径加载程序集   包含在探测中,但允许依赖于该路径   找到并加载,因为路径信息由。维护   上下文。

     

LoadFrom方法具有以下缺点。考虑使用   改为加载。

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 

备注:

您写道:But I can't create an instance of it such that I can cast it to my local IModule
具体对象必须实现您投射到的接口。我不知道我是否理解正确但是从第三方dll中的接口IModule转换到本地dll中的不同接口IModule*将无效(除非您的本地接口实现了另一个)