2011-06-28 25 views
21

Tôi đang cố tạo một bài kiểm tra đơn vị đảm bảo tất cả các lớp nghiệp vụ của tôi (tôi gọi chúng là các lớp lệnh và truy vấn) có thể được giải quyết bằng Windsor. Tôi có thử nghiệm đơn vị sau đây:Làm cách nào để lọc ra các loại <> c_DisplayClass khi đi qua các loại thông qua phản ánh?

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

này không thành công với những ngoại lệ sau đây:

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

Tôi hiểu rằng <>c__DisplayClass0 loại là do LINQ được biên soạn, nhưng làm thế nào tôi có thể lọc ra những loại mà không hardcoding tên trong truy vấn LINQ của tôi?

Trả lời

26

tôi sẽ kiểm tra từng loại cho System.Runtime.CompilerServices.CompilerGeneratedAttribute được đặt trên những.

Bạn có thể sử dụng Type.IsDefined, vì vậy mã sẽ giống như thế này:

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

    // use type... 
} 
+5

Bạn có thể sử dụng 'type.IsDefined' để làm cho cuộc sống đơn giản hơn một chút. –

+0

@Jon, Cảm ơn! Tôi sẽ phải nhớ IsDefined ... Nhiều gọn gàng hơn! –

+0

Mã sử ​​dụng Phản ánh đang chạy tốt có thể bị hỏng vì VS2015! Tôi có mã đã trả về biểu thức đúng (một 'Danh sách ') từ một MethodCall. Bây giờ nó đang trả về một '<> c__DisplayClass36_0) .CS $ <> 8__locals1'. Lưu ý rằng đây là một 'MemberExpression' (nó là một' ConstantExpression' chứa danh sách là giá trị)). Bây giờ tôi phải làm theo hướng dẫn bổ sung này và sau đó lấy giá trị của một trường 'CS $ <> 8__locals1' để lấy danh sách của tôi. –

4

Kiểm tra sự hiện diện của thuộc tính [CompilerGenerated].

-1

Bạn cần phải lọc ra các lớp học năng động như thế này

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

số Đó không phải là một lớp học năng động. – SLaks

+0

System.Type không có thuộc tính IsDynamic – KallDrexx

+0

Bạn nói đúng. Tôi đã suy nghĩ hội đồng thay vì các lớp học – boca

11

lớp Rõ ràng lồng không nhận được thuộc tính [CompilerGenerated] áp dụng đối với họ.

Tôi đã bỏ qua phương pháp đơn giản này để xử lý trường hợp này.

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

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

Một lớp học mà thể hiện hành vi này sẽ trông như thế này:

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

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

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

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

Đây là câu trả lời đúng. Thumbs up! – Rookian

+0

Tôi gặp rắc rối với Mono với câu trả lời được chấp nhận vì Mono tạo ra những thứ hơi khác một chút (rõ ràng). Điều này hoạt động hoàn hảo. Cảm ơn. –

Các vấn đề liên quan