2014-10-08 21 views
7

Poszukuję sposobu na uzyskanie wszystkich klas dziedziczących ogólną klasę abstrakcyjną i wykonanie metody na każdej z tych klas.Uzyskaj wszystkie odziedziczone klasy ogólnej klasy abstrakcyjnej

Śledzę ten Change parameter type when implementing an abstract method mieć implementacje klasy chcę, coś podobnego do tego:

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 
    } 
}  

To find działa, aż muszę uzyskać wszystkie Klasa A & B i wywołaj Search() metoda dla każdej z klas. Z non-rodzajowego klasy abstrakcyjnej, mogłem użyć następującego fragmentu kodu, aby uzyskać klas

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

Następnie, w jaki sposób można uzyskać wszystkie klasy A i B, które dziedziczą z AbstractRequest<AResponse> i AbstractRequest<BResponse>?

Edytuj: Zapomniałem wspomnieć. Załóżmy, że będzie wiele implementacji podobnych do A lub B i będą one dodawane z czasem. Chciałbym mieć "elegancki" (jeśli to możliwe) rozwiązanie, więc później muszę tylko zająć się implementacją C, D, itp.

Dzięki!

Odpowiedz

2

rzeczywiście coraz instancję powołać Szukaj() (i tylko wyszukiwanie) można wykonać, dzieląc klasę abstrakcyjną:

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

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

a następnie można użyć oryginalnego (non-generic) kod:

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; 

(stary, roztwór odpadł)

myślę, że chciałbym zrobić coś takiego (niesprawdzone):

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

Powinno to obejmować wszystko w hierarchii dziedziczenia, korzystając z ograniczenia typu na AbstractRequest.

+0

Człowieku, twoja zredagowana odpowiedź jest dokładnie tym, czego potrzebuję !!! Przetestowany i działał doskonale w moim przypadku. Dziękuję Ci bardzo! –

1

Coś jak to powinno załatwić sprawę:

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

Albo jeśli chcesz dostać wszystkie klasy, które dziedziczą z klasy generycznej AbstractRequest można użyć:

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

Dziękuję za odpowiedź! Zapomniałem wspomnieć, że jest to tylko 2 z wielu implementacji podobnych do A lub B i będą dodawane z czasem. To na pewno zadziała, ale chciałbym mieć bardziej eleganckie rozwiązanie, więc później będę musiał tylko zająć się implementacją C, D, itp. –

+0

okey, wtedy zobacz moją edycję, powinna zrobić dokładnie to, co chcesz. –

+1

zezwala na typeof (AbstractRequest <>), to co powiedziałeś jest prawdziwe tylko podczas tworzenia instancji typu. –

-1

ten pracował dla mnie na kilku oddzielnych projektów

/// <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; 
} 

Aby instancji, a następnie wykonać metodę, można spróbować tego wzoru:

// 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

Dzięki za odpowiedź! Myślę, że twoje rozwiązanie jest praktycznie takie samo jak to, co zrobiłem. Problem polega na tym, że 'MyType' jest typem ogólnym (w moim przypadku' AbstractRequest ', a klasy A i B dziedziczą z klas bardziej szczegółowych,' AbstractRequest 'i' AbstractRequest '. –

Powiązane problemy