如何正确投射通过反射创建的对象

时间:2020-03-05 18:44:12  来源:igfitidea点击:

我试图把头放在反射上,所以我决定将插件功能添加到正在编写的程序中。理解概念的唯一方法是弄脏手指并编写代码,所以我走了一条路,创建了一个简单的接口库,该接口库由IPlugin和IHost接口组成,一个实现IPlugin的类的插件实现库,以及一个简单的方法。实例化IHost实现类的控制台项目,该类对插件对象进行简单的工作。

使用反射,我想遍历插件实现dll中包含的类型并创建类型的实例。我可以使用此代码成功实例化类,但无法将创建的对象强制转换为接口。

我尝试了这段代码,但无法按预期方式投射对象o。我使用调试器逐步完成了该过程,并调用了适当的构造函数。快速监视对象o向我展示了它具有在实现类中希望看到的字段和属性。

loop through assemblies
  loop through types in assembly
    // Filter out unwanted types
    if (!type.IsClass || type.IsNotPublic || type.IsAbstract )
      continue;
    // This successfully created the right object
    object o = Activator.CreateInstance(type);
    // This threw an Invalid Cast Exception or returned null for an "as" cast
    // even though the object implemented IPlugin      
    IPlugin i = (IPlugin) o;

我使代码与此一起工作。

using System.Runtime.Remoting;
ObjectHandle oh = Activator.CreateInstance(assembly.FullName, type.FullName);
// This worked as I intended
IPlugin i = (IPlugin) oh.Unwrap();
i.DoStuff();

这是我的问题:

  • Activator.CreateInstance(Type t)返回一个对象,但是我无法将该对象转换为该对象实现的接口。为什么?
  • 我应该一直在使用不同的CreateInstance()重载吗?
  • 与反射相关的提示和技巧是什么?
  • 我有没有得到反思的一些关键部分?

解决方案

回答

类型是否不是公共的,如果是,请调用一个布尔值的重载:

Activator.CreateInstance(type, true);

另外,在第一个示例中,查看o是否为null,如果不是,则打印出o.GetType()。Name以查看其实际含义。

回答

@哈克

我试图使伪代码保持简单。 foreach占用了大量空间和括号。我澄清了。

o.GetType()。FullName返回Plugins.Multiply,这是预期的对象。 Plugins.Multiply实现IPlugin。我在调试器中逐步执行了多次过程,直到晚上放弃为止。无法弄清楚为什么我不能投射它,因为我看着构造函数着火,直到对整个混乱感到脾气暴躁为止。今天晚上回到了它并使它工作,但是我仍然不明白为什么在第一个代码块中强制转换失败。第二个代码块有效,但对我来说感觉很不错。

回答

我只是在这里猜测,因为从代码中,我们在哪里定义IPlugin接口并不明显,但是如果我们无法在主机应用程序中进行转换,则我们可能在主机程序集中具有IPlugin接口,然后同时插件程序集。这行不通。

最简单的方法是在主机程序集中将IPlugin接口标记为公共,然后让插件程序集引用主机应用程序程序集,因此这两个程序集都可以访问相同的接口。

回答

@lubos hasko

你把它钉在鼻子上了。我的原始设计确实具有三个不同的程序集,其中主机和插件实现均引用了插件接口程序集。

我尝试了带有主机实现和接口程序集以及插件实现程序集的单独解决方案。在该解决方案中,第一块中的代码按预期工作。

我们给了我更多思考的机会,因为我不太理解为什么引用同一个程序集的两个程序集不会从同一个程序集中得到相同的类型。

回答

我只是试图自己解决这个问题,却迷失了答案!

我有3个不同的Cproject

  • A-插件接口项目
  • B-主机exe项目->参考A
  • C-插件实施项目->参考A

我也遇到了转换错误,直到我更改了插件接口项目的程序集名称以匹配我要转换的名称空间。

例如。

IPluginModule pluginModule = (IPluginModule)Activator.CreateInstance(curType);

之所以失败,是因为定义了IPluginModule接口的程序集称为" Common",但是-typeI强制转换为" Blah.Plugins.Common.IPluginModule"。

我将接口proj的Assembly名称更改为'Blah.Plugins.Common',这意味着强制转换成功。

希望这种解释对某人有帮助。返回代码。

回答

hmmm ...如果我们正在使用Assembly.LoadFrom加载程序集,请尝试将其更改为Assembly.LoadFile。

为我工作

从这里:http://www.eggheadcafe.com/community/aspnet/2/10036776/solution-found.aspx