2014-10-08 18 views
7

Tôi đang tìm một số cách để có được tất cả các lớp thừa kế một lớp trừu tượng chung và thực hiện một phương thức trên mỗi lớp đó.Nhận tất cả các lớp được thừa kế của một lớp trừu tượng chung

Tôi đã làm theo Change parameter type when implementing an abstract method này để có việc triển khai lớp tôi muốn, một cái gì đó tương tự như sau:

public abstract class AbstractRequest<TResponseData> 
       where TResponseData : IResponseData 
{ 
    public abstract void Search(); 
    public abstract GoodData BindData(TResponseData data); 
} 

public interface IResponseData 
{ 
} 

public class AResponse : IResponseData 
{ 
} 

public class BResponse : IResponseData 
{ 
} 

public class A : AbstractRequest<AResponse> 
{ 
    public override void Search() 
    { 
     // get AResponse 
     // Call to BindData() with AResponse 
    } 
    public override GoodData BindData(AResponse data) 
    { 
     // Bind the data from AResponse to GoodData 
    } 
} 

public class B : AbstractRequest<BResponse> 
{ 
    public override void Search() 
    { 
     // Get BResponse 
     // Call to BindData() with BResponse 
    } 
    public override GoodData BindData(BResponse data) 
    { 
     // Bind the data from BResponse to GoodData 
    } 
}  

này find đang làm việc, cho đến khi tôi cần để có được tất cả các hạng A & B và gọi Search() phương pháp cho mỗi lớp. Với một lớp trừu tượng không chung chung, tôi có thể sử dụng đoạn mã sau để có được lớp

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

Sau đó, làm thế nào tôi có thể nhận được tất cả các lớp A và B kế thừa từ AbstractRequest<AResponse>AbstractRequest<BResponse>?

Chỉnh sửa: Tôi quên đề cập đến. Giả sử rằng sẽ có nhiều triển khai tương tự như A hoặc B và sẽ được thêm vào theo thời gian. Tôi muốn có một giải pháp "thanh lịch" (nếu có thể) để sau này, tôi chỉ cần chăm sóc việc thực hiện C, D, v.v.

Cảm ơn!

Trả lời

2

Trên thực tế nhận được dụ để gọi Tìm kiếm() (và chỉ tìm kiếm) có thể được thực hiện bằng cách chia nhỏ lớp trừu tượng:

public abstract class AbstractRequest 
{ 
    public abstract void Search(); 
} 

public abstract class AbstractRequest<TResponseData> : AbstractRequest 
      where TResponseData : IResponseData 
{ 
    public abstract GoodData BindData(TResponseData data); 
} 

Và sau đó bạn có thể sử dụng ban đầu (không chung chung) mã của bạn:

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

(Cũ, giải pháp vỡ)

Tôi nghĩ rằng tôi sẽ làm một cái gì đó như thế này (chưa được kiểm tra):

var abstractRequestTypes = 
    (from t in Assembly.GetExecutingAssembly().GetTypes() 
    where t.IsClass && 
      typeof(IResponseData).IsAssignableFrom(t) 
    select typeof(AbstractRequest<>).MakeGenericType(t)).ToList(); 

var instanceTypes = from t in Assembly.GetExecutingAssembly().GetTypes() 
    where t.IsClass && 
      abstractRequestTypes.Any(dt => dt.IsAssignableFrom(t)); 

Điều này phải bao gồm mọi thứ trong hệ thống phân cấp thừa kế, lợi dụng ràng buộc loại trên AbstractRequest.

+0

Người đàn ông, câu trả lời đã chỉnh sửa của bạn chính xác là những gì tôi cần !!! Thử nghiệm, và làm việc hoàn toàn tốt trong trường hợp của tôi. Cảm ơn nhiều! –

1

Something như thế này nên làm như lừa:

from t in Assembly.GetExecutingAssembly().GetTypes() 
where t.IsClass && 
     (typeof(AbstractRequest<AResponse>).IsAssignableFrom(t) || 
     typeof(AbstractRequest<BResponse>).IsAssignableFrom(t)) 
select t; 

Hoặc nếu bạn muốn có được tất cả các lớp kế thừa từ lớp generic AbstractRequest bạn có thể sử dụng:

from t in Assembly.GetExecutingAssembly().GetTypes() 
where t.IsClass && 
     t.BaseType != null && 
     t.BaseType.GetGenericTypeDefinition() == typeof(AbstractRequest<>) 
select t; 
+0

Cảm ơn bạn đã trả lời! Tôi quên đề cập rằng nó chỉ là 2 trong số nhiều triển khai tương tự như A hoặc B, và sẽ được thêm vào theo thời gian. Điều này chắc chắn sẽ làm việc, nhưng tôi muốn có một giải pháp thanh lịch hơn để sau này, tôi chỉ cần chăm sóc việc thực hiện C, D, vv –

+0

okey sau đó xem chỉnh sửa của tôi, nó nên làm chính xác những gì bạn muốn. –

+1

nó cho phép typeof (AbstractRequest <>), những gì bạn nói là chỉ đúng khi khởi tạo kiểu. –

-1

này đã làm việc cho tôi trên một vài dự án riêng biệt

/// <summary> 
/// Find all subclasses of a given type via reflection 
/// </summary> 
/// <typeparam name="T">Parent class type</typeparam> 
/// <returns></returns> 
public Type[] GetAllSubclasses<T>() where T : class 
{ 
    Type[] types = Assembly.GetExecutingAssembly().GetTypes() 
          .Where(t => t.IsSubclassOf(typeof (T))).ToArray(); 

    return types; 
} 

Để nhanh chóng và sau đó thực hiện một phương pháp, bạn có thể thử mô hình này:

// Create new instances, then use those to execute some method. 
foreach (Type T in GetAllSubclasses<MyType>()) 
{ 
    MyType mt = (MyType) Activator.CreateInstance(T); 
    mt.MyMethod(someArgs); 
} 
+0

Cảm ơn câu trả lời của bạn! Tôi nghĩ giải pháp của bạn hầu như giống như những gì tôi đã làm. Vấn đề là 'MyType' là một kiểu generic (trong trường hợp của tôi là' AbstractRequest ', và lớp A và B sẽ kế thừa từ các lớp cụ thể hơn,' AbstractRequest 'và' AbstractRequest '. –

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