2012-08-01 67 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,然後按照預期工作。