2014-10-08 10 views
7

मैं सामान्य वर्ग वर्ग के सभी वर्गों को प्राप्त करने के लिए कुछ तरीकों की तलाश में हूं, और उन वर्गों में से प्रत्येक पर एक विधि का प्रदर्शन करता हूं।एक सामान्य सार वर्ग के सभी विरासत वर्ग प्राप्त करें

मैं, कुछ इसी तरह यह करने के लिए वर्ग कार्यान्वयन मैं चाहता हूँ के लिए इस Change parameter type when implementing an abstract method निम्नलिखित किया गया है:

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

यह काम कर रहा है खोजने के, जब तक मैं सभी एक & बी वर्ग हो और आह्वान करने के लिए की जरूरत है प्रत्येक कक्षा के लिए Search() विधि। एक गैर सामान्य सार वर्ग के साथ, मैं निम्नलिखित स्निपेट का उपयोग वर्गों

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

फिर प्राप्त करने के लिए कर सकता है, मैं सभी वर्गों ए और बी है कि AbstractRequest<AResponse> और AbstractRequest<BResponse> से विरासत कैसे मिल सकता है?

संपादित करें: मैं उल्लेख करना भूल गया। आइए मान लें कि ए या बी के समान कई कार्यान्वयन होंगे, और समय के साथ जोड़ा जाएगा। मैं बाद में एक "सुरुचिपूर्ण" (यदि संभव हो) समाधान करना चाहता हूं, तो मुझे केवल कार्यान्वयन सी, डी, आदि की देखभाल करने की आवश्यकता है

धन्यवाद!

उत्तर

2

असल में खोजें आह्वान करने के लिए उदाहरण हो रही() (और केवल खोज) अमूर्त वर्ग को तोड़कर किया जा सकता है:

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

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

और फिर आप अपने मूल (गैर सामान्य) कोड का उपयोग कर सकते हैं:

मुझे लगता है कि मैं कुछ इस तरह (untested) करना होगा

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; 

(पुराना, भंडाफोड़ समाधान):

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

इसे AbstractRequest पर प्रकार की बाधा का लाभ उठाने, विरासत पदानुक्रम में कुछ भी शामिल करना चाहिए।

+0

मैन, आपका संपादित उत्तर बिल्कुल वही है जो मुझे चाहिए !!! परीक्षण किया, और मेरे मामले में पूरी तरह से ठीक काम किया। आपका बहुत बहुत धन्यवाद! –

1

कुछ इस तरह चाल करना चाहिए:

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

या यदि आप सभी वर्गों है कि जेनेरिक वर्ग से विरासत AbstractRequest आप उपयोग कर सकते हैं मिल चाहते हैं:

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

जवाब के लिए धन्यवाद! मैं यह उल्लेख करना भूल गया कि यह ए या बी के समान कई कार्यान्वयनों में से केवल 2 है, और समय के साथ जोड़ा जाएगा। यह निश्चित रूप से काम करेगा, लेकिन मैं बाद में एक और अधिक सुरुचिपूर्ण समाधान करना चाहता हूं, मुझे केवल कार्यान्वयन सी, डी, आदि की देखभाल करने की आवश्यकता है –

+0

ओकी फिर मेरा संपादन देखें, यह वही करना चाहिए जो आप चाहते हैं। –

+1

यह टाइपफ (AbstractRequest <>) की अनुमति देता है, जो आपने कहा था, उस प्रकार को तुरंत चालू करते समय केवल सत्य है। –

-1

यह कुछ अलग परियोजनाओं

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

पर मेरे लिए काम किया है का दृष्टांत और फिर एक विधि पर अमल करने के लिए, आप इस पैटर्न की कोशिश कर सकते हैं:

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

आपके उत्तर के लिए धन्यवाद! मुझे लगता है कि आपका समाधान वही है जो मैंने किया था। समस्या यह है कि 'माईटाइप' एक सामान्य प्रकार है (मेरे मामले में 'सार सारणी <आईआरएसस्पॉन्सडाटा>', और कक्षा ए और बी अधिक विशिष्ट वर्गों, 'सार सारणी ' और 'सार सारणी ' से प्राप्त होगा। –

संबंधित मुद्दे