2012-08-01 71 views
2

随着类型平等检查

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)); 

然而,当测试时,这个检查总是失败,尽管我绝对在列表中有这种类型的对象。

在我的理解中,它应该返回在CompositionPlugins -List中找到的第一个MyCompositionPlugin实例。

我的类型检查是否错误?为什么?它是如何正确地完成的?

+0

放一些更多的代码。你如何生成ofType参数?为什么测试失败?你调试了吗? – 2012-08-01 14:20:45

+1

@tostringtheory它会返回确切的类型。可能是一个继承CompositionPlugins的类 – 2012-08-01 14:21:58

+0

我增加了一些代码和我期望的返回值。 – 2012-08-01 14:27:02

回答

0

事实证明,我开始留出了问题,认为它并不重要的信息,真是太毕竟。

MyCompositionPluginCompositionPlugin都在不同的程序集中定义,执行程序在运行时动态加载。

的.NET的运行现在consideres从不同组件加载的类型另一个比一个由执行组件引用,渲染MyCompositionPlugin -Type在Program被认为不等于从另一个组件加载的MyCompositionPlugin,即使他们实际上是一样的。

将两者相比较的解决方案(即它们在常识中是相同的“类”)是将其分解为定义的程序集的字符串相等,这可以说是肮脏的,但是招。

public CompositionPlugin GetCompositionPlugin(Type ofType) 
{ 
    foreach (CompositionPlugin plugin in CompositionPlugins) 
     if (ofType.AssemblyQualifiedName.Equals(plugin.GetType().AssemblyQualifiedName)) 
      return plugin; 

    throw new ArgumentException("A composition plugin of type " + ofType.FullName + " could not be found"); 
} 

CUDOS到Paolo Falabella谁指着this question

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"); 
    } 
} 
+1

你的解决方案不起作用,因为'is'需要实际的类型,我没有。我有一个变量。 – 2012-08-01 14:15:01

+2

他有一个'Type'对象,'X is Type'不起作用。 – vcsjones 2012-08-01 14:15:20

+0

正如@vcsjones所说,这不起作用,但由于两个原因,它不起作用。 1.您需要类型名称而不是类型的实例。 2.“is”不像“Equals”。 '是'是完全或继承的形式。 “Equals”完全是唯一的。 – 2012-08-01 14:16:00

7

你想在你的使用类型IsAssignableFrom

if (ofType.IsAssignableFrom(plugin.GetType()) 

Equals只能处理其中的类型是正是相同的情况。 IsAssignableFrom也处理ofType可能是您的插件继承的类型或实现的接口的情况。

+0

这不像'Equals'。你也包括继承。 – 2012-08-01 14:17:42

+0

@AmiramKorach就是这一点。我的想法是''ofType'是所有插件继承/实现的基类或某种类型的接口。 – vcsjones 2012-08-01 14:18:50

4

不是一个答案,但太长的评论... 你确定问题不在于你如何调用方法或填充你的集合? 比较本身应该是好的,对你的代码的这种简化版本所证实:

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 S的第4个,则返回true)

类似你这样的情况请参阅使用真值表这个例子等于:

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 
+0

我在该方法中添加了更多的代码,也许这将清除一切。我也认为比较应该按照我希望的方式工作... – 2012-08-01 14:30:21

+0

@FlorianPeschka看着你的代码似乎你正在检查一个CompositionPlugin对MyCompositionPlugin(这是我猜想继承于CompositionPlugin)。我认为这就是平等失败的原因。即vcsjones是正确的 – 2012-08-01 14:40:16

0

你的问题很可能是由于该组件加载第二次和事实为此平等失败,则最好避免再次被加载的程序集,所以你可以使用普通类型比较而不是使用那个脏字符串比较。我有同样的问题,我的插件接口是在一个单独的程序集中定义的,此程序集存在于启动文件夹中,但也存在于插件程序集文件夹中,插件程序集动态加载的地方由于接口类型相等而失败。我从插件文件夹中删除了界面dll,然后按照预期工作。