2011-06-28 311 views
21

我想創建一個單元測試,確保我的所有業務類(我稱之爲命令和查詢類)都可以與Windsor一起解決。我有以下的單元測試:如何通過反射過濾類型時過濾<> c_DisplayClass類型?

[TestMethod] 
    public void Windsor_Can_Resolve_All_Command_And_Query_Classes() 
    { 
     // Setup 
     Assembly asm = Assembly.GetAssembly(typeof(IUnitOfWork)); 
     IList<Type> classTypes = asm.GetTypes() 
            .Where(x => x.Namespace.StartsWith("MyApp.DomainModel.Commands") || x.Namespace.StartsWith("MyApp.DomainModel.Queries")) 
            .Where(x => x.IsClass) 
            .ToList(); 

     IWindsorContainer container = new WindsorContainer(); 
     container.Kernel.ComponentModelBuilder.AddContributor(new SingletonLifestyleEqualizer()); 
     container.Install(FromAssembly.Containing<HomeController>()); 

     // Act 
     foreach (Type t in classTypes) 
     { 
      container.Resolve(t); 
     } 
    } 

這失敗,出現以下異常:

No component for supporting the service MyApp.DomainModel.Queries.Organizations.OrganizationByRegistrationTokenQuery+<>c__DisplayClass0 was found 

我明白<>c__DisplayClass0類型是由於LINQ的被編譯,但我怎麼能過濾掉這些類型沒有硬編碼我的Linq查詢中的名稱?

回答

26

動態類我會檢查每個類型爲放在這些的System.Runtime.CompilerServices.CompilerGeneratedAttribute

您可以使用Type.IsDefined,所以代碼會是這個樣子:

foreach (Type type in classTypes) 
{ 
    if (type.IsDefined (typeof (CompilerGeneratedAttribute), false)) 
     continue; 

    // use type... 
} 
+5

你可以使用'type.IsDefined'使生活變得更簡單。 –

+0

@Jon,謝謝!我必須記住IsDefined ...更簡潔! –

+0

使用運行良好的反射代碼可以打破自VS2015!我有一個代碼從MethodCall返回正確的表達式('List ')。現在它返回一個'<> c__DisplayClass36_0).CS $ <> 8__locals1'。請注意,這是一個'MemberExpression'(它是一個'ConstantExpression',包含列表作爲值))。現在我必須遵循這個額外的間接尋址方式,然後獲得'CS $ <> 8_locals1'的字段值,以便獲得我的列表。 –

4

檢查是否存在[CompilerGenerated]屬性。

-1

您需要過濾掉這樣

IList<Type> classTypes = asm.GetTypes() 
           .Where(x => x.Namespace.StartsWith("MyApp.DomainModel.Commands") || x.Namespace.StartsWith("MyApp.DomainModel.Queries")) 
           .Where(x => x.IsClass && !x.IsDynamic) 
           .ToList(); 
+0

號這不是動態類。 – SLaks

+0

System.Type沒有IsDynamic屬性 – KallDrexx

+0

您是對的。我在想組件而不是類 – boca

11

顯然嵌套類沒有得到應用到他們的[CompilerGenerated]屬性。

我鞭打這個簡單的方法來處理這種情況。

bool IsCompilerGenerated(Type t) { 
    if (t == null) 
     return false; 

    return t.IsDefined(typeof(CompilerGeneratedAttribute), false) 
     || IsCompilerGenerated(t.DeclaringType); 
} 

表現出這種行爲應該是這樣的一個類:

class SomeClass { 
    void CreatesADisplayClass() { 
     var message = "foo"; 

     Action outputFunc =() => Trace.Write(message); 

     Action wheelsWithinWheels =() => 
     { 
      var other = "bar"; 

      Action wheel =() => Trace.WriteLine(message + " " + other); 
     }; 
    } 
} 
+2

這是正確的答案。豎起大拇指! – Rookian

+0

因爲Mono生成的東西有點不同(顯然),所以我在Mono上遇到了麻煩。這工作完美。謝謝。 –