2013-01-21 42 views
6

thể trùng lặp:
Finding all classes with a particular attributeTìm tất cả các lớp học với một attribut cụ

Trong một lắp ráp Tôi muốn để có được tất cả các trường của một thuộc tính lớp học đặc biệt. Nói cách khác, tôi muốn có danh sách các lớp có thuộc tính cụ thể.

Thông thường bạn sẽ có một lớp mà bạn có thể tìm nạp thuộc tính bằng cách sử dụng phương thức GetCustomAttributes.

Có thể có danh sách những người có thuộc tính cụ thể không?

+0

Bạn có nghĩa là danh sách các lớp học có thuộc tính cụ thể trong hội đồng không? Bạn có danh sách các lớp học trong phạm vi nào? – LukeHennerley

+1

Để tất cả, những người downvoted bài! Xin vui lòng, để lại bình luận cho downvotes của bạn. –

Trả lời

3
public static IEnumerable<Type> GetTypesWithMyAttribute(Assembly assembly) 
{ 
    foreach(Type type in assembly.GetTypes()) 
    { 
     if (Attribute.IsDefined(type, typeof(MyAttribute))) 
      yield return type; 
    } 
} 

Hoặc:

public static List<Type> GetTypesWithMyAttribute(Assembly assembly) 
{ 
    List<Type> types = new List<Type>(); 

    foreach(Type type in assembly.GetTypes()) 
    { 
     if (type.GetCustomAttributes(typeof(MyAttribute), true).Length > 0) 
      types.Add(type); 
    } 

    return types; 
} 

LINQ VS chuẩn phương pháp của tôi (100000 lặp):

Round 1 
My Approach:  2088ms 
Linq Approach 1: 7469ms 
Linq Approach 2: 2514ms 

Round 2 
My Approach:  2055ms 
Linq Approach 1: 7082ms 
Linq Approach 2: 2149ms 

Round 3 
My Approach:  2058ms 
Linq Approach 1: 7001ms 
Linq Approach 2: 2249ms 

đang Benchmark:

[STAThread] 
public static void Main() 
{ 
    List<Type> list; 

    Stopwatch watch = Stopwatch.StartNew(); 

    for (Int32 i = 0; i < 100000; ++i) 
     list = GetTypesWithMyAttribute(Assembly.GetExecutingAssembly()); 

    watch.Stop(); 

    Console.WriteLine("ForEach: " + watch.ElapsedMilliseconds); 

    watch.Restart(); 

    for (Int32 i = 0; i < 100000; ++i) 
     list = GetTypesWithMyAttributeLinq1(Assembly.GetExecutingAssembly()); 

    Console.WriteLine("Linq 1: " + watch.ElapsedMilliseconds); 

    watch.Restart(); 

    for (Int32 i = 0; i < 100000; ++i) 
     list = GetTypesWithMyAttributeLinq2(Assembly.GetExecutingAssembly()); 

    Console.WriteLine("Linq 2: " + watch.ElapsedMilliseconds); 

    Console.Read(); 
} 

public static List<Type> GetTypesWithMyAttribute(Assembly assembly) 
{ 
    List<Type> types = new List<Type>(); 

    foreach (Type type in assembly.GetTypes()) 
    { 
     if (Attribute.IsDefined(type, typeof(MyAttribute))) 
      types.Add(type); 
    } 

    return types; 
} 

public static List<Type> GetTypesWithMyAttributeLinq1(Assembly assembly) 
{ 
    return assembly.GetTypes() 
       .Where(t => t.GetCustomAttributes().Any(a => a is MyAttribute)) 
       .ToList(); 
} 

public static List<Type> GetTypesWithMyAttributeLinq2(Assembly assembly) 
{ 
    return assembly.GetTypes() 
       .Where(t => Attribute.IsDefined(t, typeof(MyAttribute))) 
       .ToList(); 
} 
+0

Sử dụng LINQ sẽ có khả năng tăng tốc độ những thứ ở đây thay vì lặp qua các lớp, nhưng đạt được kết quả tương tự nontheless :) – LukeHennerley

+0

Hãy thử một điểm chuẩn như vậy! –

+1

Guys Tôi không có cảm giác về tốc độ ở đây. Rõ ràng là sự kiên định của tôi. Tôi sẽ chỉ thực hiện điều này khi toàn bộ ứng dụng. Dù sao tôi cảm ơn sự nỗ lực của bạn. – mathk

1
var list = asm.GetTypes() 
      .Where(t => t.GetCustomAttributes().Any(a => a is YourAttribute)) 
      .ToList(); 
2

Bạn có thể thực hiện việc này bằng cách sử dụng reflection. Điều này sẽ giúp bạn có được List<Type> của tất cả các loại trong hội đồng hiện tại có MyAttribute.

using System.Linq; 
using System.Reflection; 

// ... 

var asmbly = Assembly.GetExecutingAssembly(); 
var typeList = asmbly.GetTypes().Where(
     t => t.GetCustomAttributes(typeof (MyAttribute), true).Length > 0 
).ToList(); 
+0

Vâng, đó là những gì tôi muốn tránh. Có vòng lặp trên tất cả các lớp của một assatic paticular không phải là khá tốt đẹp. Nhưng nếu đó là giải pháp duy nhất. – mathk

+0

@mathk Thật không may là; Nó không phải là chậm để thực hiện kiểm tra cho mỗi loại, mặc dù. Nếu bạn định sử dụng lại séc này ở nhiều nơi, bạn luôn có thể lưu trữ kết quả. –

+0

Tôi sẽ chỉ sử dụng tính năng này một lần ở đầu ứng dụng. Tôi không quan tâm đến tốc độ. Nhưng yêu cầu thời gian chạy để tạo ra tất cả các sự tái hiện nó là cái gì đó tôi không hoàn toàn là fan hâm mộ. Một số phương thức tĩnh trên lớp Attribute như: 'GetAllType', hoặc' GetAllProperties', ... sẽ đẹp hơn. – mathk

0

Với không có ví dụ mã, một giả sử bạn có một List<Type> hoặc một Assembly.

public List<Type> TypesWithAttributeDefined(Type attribute) 
{ 
    List<Type> types = assembly.GetTypes(); 
    return types.Where(t => Attribute.IsDefined(t, attribute)).ToList(); 
} 
Các vấn đề liên quan