2009-05-28 6 views
7

में परिपत्र संदर्भ से बचें यह इतना आम परिदृश्य होना चाहिए कि इसके बारे में बहुत कुछ लिखा गया है, उम्मीद है कि वास्तव में भी एक अच्छा पैटर्न है। मेरे पास एक डोमेन मॉडल है जिसमें कस्टम कंटेनर में इकाइयां होती हैं। उदाहरण (गुण और इंटरफेस संक्षिप्तता के लिए छोड़ा गया है) के लिए:डोमेन मॉडल

class Entity 
{ 
    public int Id; 
    public EntityContainer ParentContainer; 
} 


class EntityContainer 
{ 
    public int Id; 
    public IList<Entity> Entities = new List<Entity>(); 

    public void AddEntity(Entity entity) 
    { 
     entity.ParentContainer = this; 
     Entities.Add(entity); 
    } 
} 


class Main 
{ 
    public Main() 
    { 
     Entity entity1 = new Entity(); 
     Entity entity2 = new Entity(); 
     EntityContainer entityContainer = new EntityContainer(); 
     entityContainer.AddEntity(entity1); 
     entityContainer.AddEntity(entity2); 

     // Can now traverse graph easily, e.g. 
     Console.WriteLine("entity1's parent container ID = " + entity1.ParentContainer.Id); 
     Console.WriteLine("Container contains at least this entity ID: " + entityContainer.Entities[0].Id); 

    } 
} 

मैं अब आसानी से अपने वस्तु ग्राफ दोनों तरीकों से पार कर सकते हैं, लेकिन एक परिपत्र संदर्भ बनाया है। क्या निर्भरता तलाक के लिए आप तीसरे प्रकार का निर्माण करेंगे?

अग्रिम

+2

आपके पास मौजूद मॉडल में एक से अधिक अभिभावक कंटेनर के लिए एक व्यस्त रिश्ते की अनुमति नहीं है, इसलिए यदि आपके पास एकाधिक कंटेनर में कोई इकाई है तो संभवत: वैसे ही काम नहीं करेगा। – workmad3

+0

क्या आप स्पष्टीकरण दे सकते हैं कि यह परिपत्र कैसे है? जहां तक ​​मैं समझता हूं, आप पेड़ की संरचना बना रहे हैं, इसलिए मुझे नहीं पता कि सर्कुलरिटी – RobV

+0

से कहां से आती है EntityContainer और EntityContainer का संदर्भ एंटीटी का संदर्भ है। – ng5000

उत्तर

4

वृत्तीय संदर्भ, दर असल साथ गलत कुछ भी नहीं है, और वे बड़े पैमाने पर उपयोग किया जाता है .NET फ्रेमवर्क, उदाहरण के लिए XmlNode.OwnerDocument, Control.Parent।

यदि आपको पेड़ को पार करने की आवश्यकता है, तो एक बैक संदर्भ उपयोग करने के लिए ठीक है।

COM में, परिपत्र संदर्भ मुश्किल हैं क्योंकि यदि आप कंटेनर और उसके सभी बच्चों को कुछ भी सेट नहीं करते हैं, तो वस्तुओं को ठीक से साफ नहीं किया जाएगा क्योंकि बच्चे अभी भी माता-पिता के संदर्भ रखते हैं। हालांकि .NET कचरा संग्रह को इस तरह से लागू करने के तरीके में कोई समस्या नहीं है।

+0

सर्कुलर संदर्भों के साथ मुझे सामना करने वाली एक समस्या क्रमबद्धता के साथ है। आम तौर पर, यदि ऑब्जेक्ट ए में बी है और ऑब्जेक्ट बी में ए है, तो यह क्रमबद्ध नहीं होगा। इन ऑब्जेक्ट्स को आउट-ऑफ-प्रो सत्र स्थिति में डालने पर यह विशेष रूप से समस्याग्रस्त है। –

2

धन्यवाद कंटेनर प्रकार सामग्री की के बारे में पता करने की जरूरत है? यदि नहीं, जेनेरिक इस से बच सकते हैं - यानी Container<T>, जहां Container<Entity> का उपयोग करने के लिए होता है। उसके अलावा; जरूरी विवरण को एक असेंबली में एक इंटरफ़ेस (या बेस-क्लास) में दबाकर जो दोनों संदर्भ दे सकते हैं, एक आम दृष्टिकोण है।

व्यक्तिगत रूप से, मैं बच्चे को माता-पिता के बारे में जानने की आवश्यकता से बचने की कोशिश करता हूं।

इसके अलावा; ध्यान दें कि यदि आप एस्ट्रस्ट्रक्शन (इंटरफ़ेस आदि) मार्ग पर जाएं; यदि आप उपयोग कर रहे हैं (उदाहरण के लिए) xml serialization का उपयोग कर रहे हैं तो इसका एक बड़ा प्रभाव हो सकता है।


(संपादित फिर से टिप्पणी) ठीक; पहला: परिपत्र संदर्भ (एक असेंबली के भीतर) क्या समस्या है; यदि कोई नहीं, तो इसे अकेला छोड़ दो। यदि कोई समस्या है, तो आपको एक अतिरिक्त प्रकार की आवश्यकता होगी; शायद कुछ इंटरफेस ठोस प्रकार का प्रतिनिधित्व करने के लिए - यानी जहां Entity : IEntity, और EntityContainer केवल बारे में IEntity (या IEntityContainer, या दोनों के साथ vv) जानता है,

+1

बच्चे को प्रदर्शन कारणों से अपने माता-पिता के बारे में जानना आवश्यक है। – ng5000

+0

जेनेरिक वास्तविक समस्या डोमेन के लिए उपयुक्त नहीं होगा जो मैं मॉडलिंग कर रहा हूं। ये विशिष्ट प्रकार और रिश्तों हैं। – ng5000

+0

अपडेट के लिए धन्यवाद - मैं इंटरफेस जोड़ रहा हूं। मुझे लगता है कि सर्कुलर संदर्भों के साथ वास्तव में कुछ भी गलत नहीं है, इस सवाल से मुख्य दूर है। – ng5000

1

इसलिए मुझे आपके क्लास मॉडल में कोई समस्या नहीं दिखाई दे रही है लेकिन आप आसानी से एक साफ कटौती कर सकते हैं। इकाई को एक इंटरफ़ेस आईईएनटीटी लागू करें और EntityContainer को IList दबाएं और जब तक आपके पास IList का उपयोग करने के लिए कोई विशिष्ट कारण न हो, आपको IENumerable को समझना चाहिए, इससे आपके द्वारा उपयोग किए जाने वाले EntityClass के उपभोक्ता के लिए यह आसान हो जाएगा। आईईएनटीटी के किसी भी सरणी को पार करने के बाद, या आईएनएनटीटी का चयन करने वाली लिनक अभिव्यक्ति संभव होगी

+0

किसी सूची पर गणना करने योग्य। टोलिस्ट() को कॉल करना सबसे निश्चित रूप से मुफ़्त नहीं है, क्योंकि यह हमेशा एक नई सूची तैयार करता है - इसलिए इसे एक प्रतिलिपि बनाना होगा, जो ओ (एन) है। –

+0

@ पावेल नोप इसे सूची ऑब्जेक्ट को वापस करने के लिए अनुकूलित किया गया है यदि इसे किसी सूची –

+0

पर बुलाया गया है तो आप सादे गलत हैं। ILSpy के साथ System.Core.dll खोलें और 'एन्यूमेरेबल। लिलिस्ट' के कार्यान्वयन को देखें। यह सचमुच 'नई सूची() 'और एक तर्क शून्य जांच के रूप में सरल है। यह काफी जानबूझकर है - LINQ के डिजाइनर नहीं चाहते थे कि लाइब्रेरी क्लाइंट लाइब्रेरी लेखक की अपेक्षा न करें, और संभावित रूप से आंतरिक डेटा को उत्परिवर्तित करने के लिए ऑब्जेक्ट्स को कम करने में सक्षम हों। तो सभी 'to ...()' विधियां एक प्रतिलिपि बनाएंगी भले ही मूल पहले से ही उस प्रकार का हो। इसके विपरीत, 'जैसा ...()' मूल वस्तु को वापस कर देता है। –

1

सर्कुलर संदर्भित ऑब्जेक्ट्स का उपयोग करना मेरी पुस्तक में ठीक है, जिससे आप उन वस्तुओं को डिजाइन करते समय किसी प्रकार का आलसी लोडिंग पैटर्न का उपयोग कर रहे हैं।

उदा।

आप पहुंचना चाहते हैं: Company.Employee और एक और स्थिति में: कर्मचारी।कंपनी

कौन सा एक परिपत्र संदर्भ अर्थात Company.Employee.Company.Employee आदि

बनाता है इन गुणों जैसे आलसी-लोडेड नहीं कर रहे हैं एक कंपनी ऑब्जेक्ट हमेशा अपनी कर्मचारी संपत्ति लोड करता है और कर्मचारी ऑब्जेक्ट हमेशा अपनी कंपनी की संपत्ति लोड करता है, फिर जब आप डेटा स्रोत पेश करते हैं तो यह बहुत अच्छा काम करेगा।