【问题标题】:Assembly.CreateInstance type conversion returns nullAssembly.CreateInstance 类型转换返回 null
【发布时间】:2012-09-14 17:54:29
【问题描述】:

我正在尝试在运行时加载和使用 DLL,这工作正常:

var pluggin = asm2.CreateInstance("ParserTest.Interface", true) as iPluggin;

但这没有(我需要遍历特定文件夹中的 DLL 文件以找到实现 iPluggin 接口的正确文件):

...
var asm = Assembly.LoadFrom(dll.FullName);
if (asm.GetExportedTypes().FirstOrDefault(q => q.GetInterface(tName) != null) == null) continue;
Project.ProcessList.Add(asm.CreateInstance(tName, true) as iPluggin);
...

在调试模式下做一些研究发现:

asm.CreateInstance(tName, true)

返回正确的对象,但是当尝试将其转换为 iPluggin 时,结果为空。 知道为什么吗?

【问题讨论】:

  • 因为它返回一个不兼容类型的对象 (?)。
  • CreateInstance 按预期返回一个 System.Object,我看到的有效代码和无效代码之间的唯一区别是我手动提供了接口名称(“ParserTest.Interface”)第一种情况
  • as 在转换失败时返回 null 而不是引发异常,正如 Ondrej 所说。
  • 是的,但是如果它没有实现那个接口,“as”返回null。那么:该接口在哪里声明?
  • @FranCasadome 然后看起来你以某种方式加载了两次声明iPluggin 的程序集。您是否尝试过重新编译所有内容?你不是从一个陌生的地方加载那个程序集吗,或者类似的东西?

标签: c# .net-assembly


【解决方案1】:

我做了类似的事情:

private readonly Type _pluginbaseType = typeof(BasePlugin);

public AssemblyPlugin(Assembly assembly)
{

    Type[] _plugins = _assembly.GetExportedTypes()
        .Where(t => t.BaseType.IsSubclassOf(_pluginbaseType)
        .ToArray();
}

在此之后,您可以:

BasePlugin plugin = (BasePlugin)Activator.CreateInstance(pluginType);

你应该更喜欢基类而不是接口。

【讨论】:

  • 为什么基类比接口更好?
  • 好吧,我发现了一些东西:如果所有正在检查接口的 DLL 都实现了它,那么它工作正常。只要其中一个没有,其余的就返回 null,无论他们是否实现它。 ://
  • @svick:基类可以具有基本功能,而接口则不能。在这种情况下,您可能更愿意提供所有插件的特定行为。偏爱抽象基类的主要原因是版本控制,因为您总是可以在不破坏现有客户端的情况下向抽象基类添加新的虚拟成员。使用接口是不可能的。在这里:Choosing Between Classes and Interfaces.
【解决方案2】:

虽然我不明白,但谜团解决了。

定义接口 (SDK.dll) 的 DLL 也在被检查的范围内。 我在查询中手动删除了它,现在所有的炒锅都按预期删除了。 这是我的最终代码:

    var plugins =
        from fi in di.GetFiles("*.dll").Where(p => p.Name.ToUpper() != "SDK.DLL")
        let asm = Assembly.LoadFrom(fi.FullName)
        from t in asm.GetExportedTypes()
        where t.GetInterface(typeof(iPluggin).Name) != null
        select asm.CreateInstance(t.FullName, true) as iPluggin;
    Project.ProcessList.AddRange(plugins);

【讨论】:

  • 您可以使用Type.IsAssignableFrom 方法,而不是专门检查涵盖基类和接口的接口类型。并且由于您本身具有类型引用,因此请使用 Activator.CreateInstance(t) 而不是让它按类型名称在程序集中进行另一次查找(特别是因为您进行了不区分大小写的搜索。理论上可能存在同名但区分大小写!)
  • 您可能还想检查该类型是否具有无参数构造函数,或者捕获(并报告)MissingMethodException,如果提供的iPlugin 实现未实现无参数构造函数,则会触发。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-09
  • 1970-01-01
  • 1970-01-01
  • 2013-12-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多