2009-03-31 31 views
65

Theo một không gian tên đã cho, tôi có một tập hợp các lớp thực hiện một giao diện. Hãy gọi nó là ISomething. Tôi có một lớp khác (hãy gọi nó là CClass) mà biết về ISomething nhưng không biết về các lớp triển khai giao diện đó.Cách tìm tất cả các lớp thực hiện giao diện cụ thể?

Tôi muốn rằng CClass để tìm tất cả việc triển khai ISomething, khởi tạo phiên bản của nó và thực thi phương pháp.

Có ai có ý tưởng về cách thực hiện điều đó với C# 3.5 không?

+2

thể trùng lặp của [Bắt tất cả các loại mà thực hiện một giao diện với C# 3.0] (http://stackoverflow.com/questions/26733/getting-all -types-that-implement-an-interface-với-c-sharp-3-0) –

Trả lời

127

Một mã mẫu làm việc:

var instances = from t in Assembly.GetExecutingAssembly().GetTypes() 
       where t.GetInterfaces().Contains(typeof(ISomething)) 
         && t.GetConstructor(Type.EmptyTypes) != null 
       select Activator.CreateInstance(t) as ISomething; 

foreach (var instance in instances) 
{ 
    instance.Foo(); // where Foo is a method of ISomething 
} 

Sửa Added một tấm séc cho một constructor parameterless để các cuộc gọi đến CreateInstance sẽ thành công.

+9

Đề xuất dọn dẹp nhỏ xíu - sử dụng Type.EmptyTypes thay vì khởi tạo một mảng Loại trống mới. –

+0

Có cách nào để làm điều này trên tất cả các hội đồng nạp? – gregmac

+13

nevermind .. var trường = từ lắp ráp trong AppDomain.CurrentDomain.GetAssemblies() từ t trong assembly.GetTypes() nơi t.GetInterfaces(). Chứa (typeof (ISomething)) && t.GetConstructor (Type .EmptyTypes)! = Null chọn Activator.CreateInstance (t) là ISomething; – gregmac

8

Một ví dụ sử dụng LINQ:

var types = 
    myAssembly.GetTypes() 
      .Where(m => m.IsClass && m.GetInterface("IMyInterface") != null); 
2

Bạn có thể sử dụng giống như sau và may nó yêu cầu của bạn.

var _interfaceType = typeof(ISomething); 
var currentAssembly = System.Reflection.Assembly.GetExecutingAssembly(); 
var types = GetType().GetNestedTypes(); 

foreach (var type in types) 
{ 
    if (_interfaceType.IsAssignableFrom(type) && type.IsPublic && !type.IsInterface) 
    { 
     ISomething something = (ISomething)currentAssembly.CreateInstance(type.FullName, false); 
     something.TheMethod(); 
    } 
} 

Mã này có thể sử dụng một số cải tiến hiệu suất nhưng đó là sự bắt đầu.

9

Bạn có thể nhận được một danh sách các assembly được nạp bằng cách sử dụng này:

Assembly assembly = System.Reflection.AppDomain.CurrentDomain.GetAssemblies() 

Từ đó, bạn có thể nhận được một danh sách các loại trong việc lắp ráp (giả định các loại công cộng):

Type[] types = assembly.GetExportedTypes(); 

Sau đó, bạn có thể hỏi từng loại cho dù nó hỗ trợ giao diện đó bằng cách tìm giao diện đó trên đối tượng:

Type interfaceType = type.GetInterface("ISomething"); 

Không chắc chắn nếu có một cách hiệu quả hơn để làm điều này với sự phản ánh.

3
foreach (Type t in Assembly.GetCallingAssembly().GetTypes()) 
{ 
    if (t.GetInterface("ITheInterface") != null) 
    { 
     ITheInterface executor = Activator.CreateInstance(t) as ITheInterface; 
     executor.PerformSomething(); 
    } 
} 
0

lẽ chúng ta nên đi theo con đường này

foreach (var instance in Assembly.GetExecutingAssembly().GetTypes().Where(a => a.GetConstructor(Type.EmptyTypes) != null).Select(Activator.CreateInstance).OfType<ISomething>()) 
    instance.Execute(); 
Các vấn đề liên quan