使用
public abstract class CompositionPlugin { ... }
和
public class MyCompositionPlugin : CompositionPlugin { ... }
我想检查一个对象的类型是否等于给定的类型:
public class Framework {
public IList<CompositionPlugin> CompositionPlugins = new List<CompositionPlugin>();
public CompositionPlugin GetCompositionPlugin(Type ofType)
{
foreach (CompositionPlugin plugin in CompositionPlugins)
{
if (plugin.GetType().Equals(ofType))
return plugin;
}
throw new ArgumentException("A composition plugin of type " + ofType.FullName + " could not be found");
}
}
这样调用方法:
Framework framework = new Framework();
// Adding the plugin to the framework is done by loading an assembly and
// checking if it contains plugin-compatible classes (i.e. subclasses
// of <CompositionPlugin>)
framework.RegisterAssembly("E:\\Projects\\Framework\\MyPlugin\\bin\\Debug\\MyPlugin.dll");
CompositionPlugin plugin = framework.GetCompositionPlugin(typeof(MyCompositionPlugin));
然而,在测试时,这个检查总是失败,即使我肯定在我要求的列表中有这种类型的对象。
根据我的理解,它应该返回MyCompositionPlugin
- 列表中找到的CompositionPlugins
的第一个实例。
我的类型检查错了吗?为什么?它是如何正确完成的?
答案 0 :(得分:7)
您想在类型上使用IsAssignableFrom
:
if (ofType.IsAssignableFrom(plugin.GetType())
Equals
仅处理类型完全相同的情况。 IsAssignableFrom
还处理ofType
可能是您的插件继承的类型或实现的接口的情况。
答案 1 :(得分:5)
不是答案,但评论太长了...... 您确定问题不在于如何调用方法或填充集合吗? 比较本身应该没问题,正如您的代码的简化版本所示:
class A {}
bool TestType(A item, Type ofType)
{
return item.GetType().Equals(ofType);
}
现在:
Console.WriteLine(TestType(new A(), typeof(A))); // True
Console.WriteLine(TestType(new A(), typeof(string))); // False
修改强>
我认为@vcsjones是对的。您正在尝试将派生类与基类进行比较。
在行foreach (CompositionPlugin plugin in CompositionPlugins)
中,您声明插件是CompositionPlugin,但在客户端代码中,您将其与typeof(MyCompositionPlugin)
进行比较。 (重新编辑不,我错了,你的案例对应于我的Console.WriteLine
中返回true的第4个
在与您类似的场景中查看此示例的Equals真值表:
class CompositionPlugin {}
class MyCompositionPlugin : CompositionPlugin {}
// Define other methods and classes here
bool TestType(CompositionPlugin item, Type ofType)
{
return item.GetType().Equals(ofType);
}
现在
Console.WriteLine(TestType(new CompositionPlugin(),
typeof(CompositionPlugin))); //True
Console.WriteLine(TestType(new CompositionPlugin(),
typeof(MyCompositionPlugin))); //False
Console.WriteLine(TestType(new MyCompositionPlugin(),
typeof(CompositionPlugin))); //False
Console.WriteLine(TestType(new MyCompositionPlugin(),
typeof(MyCompositionPlugin))); //True
答案 2 :(得分:3)
使用关键字is
if (plugin is ofType)
return plugin;
编辑:
我必须和@vcsjones一起去这个。使用isassignablefrom功能。
但是如果你真的认为它应该可以工作,我总是创建快速函数来将调试文本写入文件。
public class Framework {
public IList<CompositionPlugin> CompositionPlugins = new List<CompositionPlugin>();
public CompositionPlugin GetCompositionPlugin(Type ofType)
{
using(var writer = System.IO.File.CreateText(@"C:\test.log"))
{
writer.WriteLine("ofType: " + ofType.toString());
foreach (CompositionPlugin plugin in CompositionPlugins)
{
writer.WriteLine("plugin: " + plugin.GetType().toString());
if (plugin.GetType().Equals(ofType))
return plugin;
}
}
throw new ArgumentException("A composition plugin of type " + ofType.FullName + " could not be found");
}
}
答案 3 :(得分:0)
事实证明,我最初忽略的信息,认为它并不重要,毕竟是这样。
MyCompositionPlugin
和CompositionPlugin
都在不同的程序集中定义,执行程序在运行时动态加载。
.NET-Runtime现在考虑从不同的程序集加载的类型而不是执行程序集引用的类型,使MyCompositionPlugin
- Program
中的类型被认为不等于{ {1}}从另一个程序集加载,即使它们实际上是相同的。
比较两者的相等性的解决方案(因为它们在常识中是相同的“类”)是将它分解为定义组件的字符串相等,这可以说是脏的,但是诀窍是
MyCompositionPlugin
的this question致敬
答案 4 :(得分:0)
您的问题很可能是因为程序集第二次加载而且相等失败,最好避免再次加载程序集,因此您可以使用普通类型比较而不是需要使用那个脏字符串比较。我遇到了同样的问题,我的插件接口是在一个单独的程序集中定义的,这个程序集存在于启动文件夹中,但也存在于插件文件夹中,动态加载的插件程序集因此导致接口类型相等失败。我从插件文件夹中删除了界面dll,之后一切都按预期工作。