2012-03-15 11 views
5

मैं निम्नलिखित इंटरफ़ेस घोषणाओं है:मैं सी # में जेनेरिक इंटरफेस के साथ किसी बच्चे ऑब्जेक्ट से किसी अभिभावक का संदर्भ कैसे दूं?

interface IOrder<T> where T: IOrderItem 
{ 
    IList<T> Items { get; set; } 
} 

interface IOrderItem 
{ 
    IOrder<IOrderItem> Parent { get; set; } // What do I put here? 
} 

मैं सूची में आइटम्स चाहते हैडर वस्तु के लिए एक संदर्भ के लिए है, इसलिए इसे हैडर से आईडी और अन्य क्षेत्रों का उपयोग कर सकते हैं।

मेरी ठोस कक्षाओं में, यह शिकायत करता है कि मैं "माता-पिता" को ठीक से लागू नहीं करता हूं।

class StoreOrder : IOrder<StoreOrderItem> 
{ 
    public IList<StoreOrderItem> Items { get; set; } 
} 

class StoreOrderItem : IOrderItem 
{  
    public StoreOrder Parent { get; set; } // This doesn't satisfy the interface 
} 

मैं IOrderItem<T> रूप IOrderItem की स्थापना और जनक प्रकार में गुजर कोशिश की, लेकिन हैडर वर्ग के बाद से वृत्तीय संदर्भ पर लेकर जाते मद वर्ग प्रकार requries ... मैं उलझन में मिल गया।

इसे ठीक से कार्यान्वित करने के तरीके पर कोई सलाह?

+0

[यह आपके लिए दिलचस्प हो सकता है] (http://msdn.microsoft.com/en-us/library/dd469487.aspx) – abatishchev

उत्तर

3

यदि आप अपने इंटरफेस को इस तरह परिभाषित करते हैं:

interface IOrder<T> where T : IOrderItem<T> 
{ 
    IList<T> Items { get; set; } 
} 
interface IOrderItem<T> where T : IOrderItem<T> 
{ 
    IOrder<T> Parent { get; set; } 
} 

फिर आप कार्यक्षमता कि आप उम्मीद कर पाने के लिए इस तरह उन्हें लागू कर सकते हैं: StoreOrder और StoreOrderItem को

interface IOrder<TOrder, TOrderItem> 
    where TOrderItem : IOrderItem<TOrder> 
{ 
    IList<TOrderItem> Items { get; set; } 
} 

interface IOrderItem<TOrder> 
{ 
    TOrder Parent { get; set; } 
} 

परिवर्तन करना:

class StoreOrder : IOrder<StoreOrderItem> 
{ 
    public IList<StoreOrderItem> Items { get; set; } 
} 
class StoreOrderItem: IOrderItem<StoreOrderItem> 
{ 
    public IOrder<StoreOrderItem> Parent { get; set; } 
} 
+0

यह कंपाइलर त्रुटि को सुधारता है, लेकिन 'स्टोरर' प्रॉपर्टी के प्रकार को 'IOrder ' पर 'स्टोरऑर्डर' के बजाय स्ट्रिप्स करता है जैसे कि यह प्रश्नकर्ता प्रयास कर रहा था। इसलिए, यदि आपके पास 'StoreOrderItem' है और' IOrder .Theems' प्रॉपर्टी पर काम करने के अलावा 'माता-पिता' के साथ कुछ भी करना चाहते हैं तो आपको पहले 'माता-पिता' को 'StoreOrder'' पर डालना होगा। – devgeezer

+2

@devgeezer - आप सही हैं। हालांकि मेरा कार्यान्वयन किसी भी 'IOrder ' कार्यान्वयन को माता-पिता होने की अनुमति देगा। कुछ भी जो 'IOrderItem ' को अपने माता-पिता के बारे में जानने की आवश्यकता है, को 'IOrder ' इंटरफ़ेस में कार्यान्वित किया जाना चाहिए, क्योंकि दोनों के बीच संबंध इंटरफ़ेस स्तर पर परिभाषित किया गया है और कार्यान्वयन स्तर नहीं है। –

+0

उत्कृष्ट बिंदु। मैं सोच रहा हूं कि मैंने इस सवाल में बहुत अधिक इरादा पढ़ा है। +1 – devgeezer

1
class StoreOrder : IOrder<StoreOrderItem> 
{ 
    public int Id { get; set; } 
} 

class StoreOrderItem : IOrderItem 
{  
    public IOrder<IOrderItem> Parent { get; set; } // This doesn't satisfy the interface 
} 

आप विशेषज्ञ नहीं हो सकता है - IOrder<IOrderItem> से StoreOrder

+0

आईडी क्यों? क्यों नहीं 'IOrder .IList '? – abatishchev

+0

आप सही हैं, कोई संकेत क्यों नहीं। संपादित। – IronicMuffin

+0

@Eugen: क्या आपका कोड संकलित है? – abatishchev

0

घोषणा अधिक सामान्य है इंटरफेस को पूरा करने के:

class StoreOrder : IOrder<StoreOrderItem> 
{ 
    // interface members 
    public IList<StoreOrderItem> Items { get; set; } 

    // own members 
    public int Id { get; set; } 
} 

class StoreOrderItem : IOrderItem 
{ 
    public IOrder<IOrderItem> Parent { get; set; } 
} 

कस्टम सदस्यों तक पहुंचने के लिए आप कास्ट करना होगा:

class StoreOrderItem : IOrderItem 
{ 
    void Test() 
    { 
     int id = ((StoreOrder)this.Parent).ID; 
    } 
} 
1

यहाँ इंटरफेस को बदलने के लिए एक समाधान है इंटरफ़ेस परिवर्तनों का समर्थन करने के लिए और बाद में परीक्षण के लिए प्रत्येक को कुछ गुण जोड़ना:

class StoreOrder: IOrder<StoreOrder, StoreOrderItem> 
{ 
    public DateTime Date { get; set; } 
    public IList<StoreOrderItem> Items { get; set; } 
} 

class StoreOrderItem : IOrderItem<StoreOrder> 
{ 
    public string ItemName { get; set; } 
    public decimal ItemPrice { get; set; } 
    public StoreOrder Parent { get; set; } 
} 

... और अब StoreOrder और StoreOrderItem उदाहरणों बनाने, और उनके माध्यम से ज्ञान प्राप्त उन्हें डाल:

void Main() 
{ 
    var so = new StoreOrder { Date = DateTime.Now }; 
    var item = new StoreOrderItem { 
      Parent = so, 
      ItemName = "Hand soap", 
      ItemPrice = 2.50m }; 
    so.Items = new [] { item }; 

    Console.WriteLine(item.Parent.Date); 
    Console.WriteLine(so.Items.First().ItemName); 
} 

... जब रन मुद्रित:

3/16/2012 10:43:55 AM 
Hand soap 

एक अन्य विकल्प है उपरोक्त स्क्रैप करने के लिए और this solution लें और वांछित प्रकार के साथ अभिभावक संपत्ति जोड़कर और कॉल-साइट पर कास्टिंग से बचने के लिए स्पष्ट इंटरफ़ेस कार्यान्वयन का उपयोग करके इसे बदलें, इस तरह की एक StoreOrderItem कार्यान्वयन कुछ के लिए कर रही है:

class StoreOrderItem : IOrderItem 
{ 
    public string ItemName { get; set; } 
    public decimal ItemPrice { get; set; } 
    public StoreOrder Parent { get; set; } // note: original implementation 

    IOrder<IOrderItem> IOrderItem.Parent { // explicit interface implementation 
     get { return (IOrder<IOrderItem>)this.Parent; } 
     set { this.Parent = (StoreOrder)value; } 
    } 
} 

ऊपर की मेरी पसंदीदा IOrder को दो सामान्य मापदंडों और IOrderItem पर स्वेच्छापूर्ण सामान्य पैरामीटर के साथ ऊपर पहला प्रस्ताव है। एक पिछले संस्करण जिसे मैंने पोस्ट किया था और अब संपादित किया है, दोनों एक ही दो सामान्य प्रकारों के साथ एक ही बाधाओं के साथ इंटरफेस करते थे।मुझे लगा जैसे यह थोड़ा ओवरबोर्ड जा रहा था इसलिए मैंने इसे उपर्युक्त कार्यान्वयन पर वापस देखा। यद्यपि TOrder पर बाधाओं की पूरी कमी है, IOrderItem पर पैरामीटर टाइप करें - इसके स्थान पर अन्य प्रकारों को झुकाव करने का प्रयास (उदाहरण के लिए, object) परिणामस्वरूप संकलन त्रुटियों में आया। TOrder का उपयोग करके इसे T कॉल करने के बजाय प्रकार की बाधा की अनुपस्थिति में अपेक्षित प्रकार के बारे में एक संकेत प्रदान करता है। यह मेरा अंतिम संपादन होगा - मुझे लगता है कि यह मेरे प्रयासों का सबसे संक्षिप्त है; यदि आप उत्सुक हैं तो मैं पूर्व कार्यान्वयन प्रदान कर सकता हूं जिसमें इंटरफेस पर डबल-जेनेरिक-बाधित-प्रकार थे, लेकिन कम से कम यह मेरा समाधान पसंद करता है। चियर्स!

+0

मैंने तब से सीखा है कि मेरे पहले समाधान का नाम है: "उत्सुकता से आवर्ती टेम्पलेट पैटर्न"। एसओ टैग [सीआरटीपी]। http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern – devgeezer

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

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