2009-04-02 12 views
7

के लिए सामान्य वर्ग डाली मैं वर्गों निम्नलिखित है:ग # - इसके आधार गैर सामान्य वर्ग

public abstract class CustomerBase 
{ 
    public long CustomerNumber { get; set; } 
    public string Name { get; set; } 
} 

public abstract class CustomerWithChildern<T> : CustomerBase 
    where T: CustomerBase 
{ 
    public IList<T> Childern { get; private set; } 

    public CustomerWithChildern() 
    { 
     Childern = new List<T>(); 
    } 
} 

public class SalesOffice : CustomerWithChildern<NationalNegotiation> 
{ 
} 

SalesOffice सिर्फ कुछ वर्गों जो ग्राहक पदानुक्रम के विभिन्न स्तरों का प्रतिनिधित्व करते हैं में से एक है। अब मुझे इस पदानुक्रम से कुछ बिंदु (ग्राहकबेस) से घूमने की जरूरत है। मैं प्रतिबिंब का उपयोग किए बिना कार्यान्वित करने का तरीका नहीं समझ सकता। मैं कुछ इस तरह कार्यान्वित करना चाहता हूं:

public void WalkHierarchy(CustomerBase start) 
    { 
     Print(start.CustomerNumber); 
     if (start is CustomerWithChildern<>) 
     { 
      foreach(ch in start.Childern) 
      { 
       WalkHierarchy(ch); 
      } 
     } 
    } 

क्या कोई मौका है कि मैं इस काम की तरह कुछ प्राप्त कर सकता हूं?


सुझाव के आधार पर समाधान है-childern इंटरफ़ेस मैं कार्यान्वित:

public interface ICustomerWithChildern 
{ 
    IEnumerable ChildernEnum { get; } 
} 

public abstract class CustomerWithChildern<T> : CustomerBase, ICustomerWithChildern 
    where T: CustomerBase 
{ 
    public IEnumerable ChildernEnum { get { return Childern; } } 

    public IList<T> Childern { get; private set; } 

    public CustomerWithChildern() 
    { 
     Childern = new List<T>(); 
    } 
} 

    public void WalkHierarchy(CustomerBase start) 
    { 
     var x = start.CustomerNumber; 
     var c = start as ICustomerWithChildern; 
     if (c != null) 
     { 
      foreach(var ch in c.ChildernEnum) 
      { 
       WalkHierarchy((CustomerBase)ch); 
      } 
     } 
    } 

उत्तर

2

मेरा मानना ​​है कि आप एक इंटरफेस चलने के निर्धारण के लिए लुकअप करना चाहते हैं।

तो शायद एक "IWalkable" इंटरफेस है कि जानकारी की पैदल दूरी पर ऐसा करने के लिए की जरूरत को उजागर करता है जोड़ने के लिए, तो आप अपने विधि से पारित कर दिया वस्तु इंटरफ़ेस लागू करता है, तो देखने के लिए जाँच बना सकते हैं।

2

और "के रूप में" केवल पर काम पूरी तरह से योग्य सामान्य प्रकार "है"।

वर्कअराउंड सहित विवरण के लिए this MSDN discussion देखें।

मैंने देखा है कि सबसे आम कामकाज उस मिश्रण में एक इंटरफ़ेस जोड़ना है जो आपके ग्राहक WithChildren लागू कर सकता है, और उस इंटरफ़ेस की जांच करें।

7

आप वॉक हाइरार्ची विधि को बेस क्लास में ले जा सकते हैं और इसे वर्चुअल बना सकते हैं। बेस क्लास कार्यान्वयन केवल वर्तमान नोड को संसाधित करेगा। CustomerWithChildern<T> कक्षा के लिए, ओवरराइड वास्तविक चलना होगा।

+0

यह सबसे अच्छा समाधान है के रूप में यह चलने कार्यान्वयन समाहित और सिर्फ फोन करने वाले के लिए मजबूर कार्यान्वयन विवरण के बारे में पता होने के लिए बिना सही काम करता है। – recursive

+0

नामित किसी व्यक्ति से उच्च प्रशंसा, "रिकर्सिव"। ;-) –

+0

मेरी आखिरी बड़ी .NET परियोजना की एक समान आवश्यकता थी, और जॉन सॉंडर्स का तरीका उतना ही है जितना मैंने किया था। कई चीजें बहुत आसान बना दिया :) – OregonGhost

0

स्पष्ट रूप से उस विधि के साथ, नहीं। हालांकि आप एक इंटरफ़ेस के साथ समान कार्यक्षमता प्राप्त कर सकते हैं। असल में, आप केवल अपनी जेनेरिक क्लास को IENumerable लागू कर सकते हैं। यह भी ध्यान देने योग्य है कि प्रकार की सुरक्षा सुनिश्चित करने के लिए आपकी कक्षा में "जहां टी: ग्राहकबेस" होना चाहिए।

1

मुझे लगता है कि जेनेरिक कक्षाओं के साथ पहली बार काम करते समय हर कोई इस "मुद्दे" को हिट करता है।

आपका पहला समस्या अपने प्रश्न शब्दों में की ओर संकेत किया गया है: एक खुला सामान्य प्रकार एक बंद एक के लिए आधार वर्ग नहीं है। यहां कोई ओओ रिश्ते नहीं है। वास्तविक आधार वर्ग ग्राहकबेस है। एक "खुला" सामान्य प्रकार आधे पूर्ण वर्ग की तरह है; प्रकार तर्कों को निर्दिष्ट करना इसे बंद कर देता है, इसे बंद कर देता है।

आप कर सकते हैं:

Type t = typeof(CustomerWithChildern<>) 

हालत

typeof(CustomerWithChildern<>).IsAssignableFrom(CustomerWithChildern<Foo>) 

हमेशा गलत हो जाएगा।

-Oisin

3

इस प्रयास करें:

if(start.GetType().GetGenericTypeDefinition() == typeof(CustomerWithChildern<>)) 
संबंधित मुद्दे