6

को हल करने के लिए एकता व्यवहार मैं इसे थोड़ा और समझने के लिए एकता के साथ खेल रहा हूं, और निम्नलिखित परिदृश्य में आया। अगर मैं एक ही प्रकार को दो बार पंजीकृत करना चाहता था, लेकिन एक सिंगलटन होने के साथ, मैं Resolve कैसे कॉल कर सकता हूं ताकि केवल सिंगलटन लौटाया जा सके? मैं समझता हूं कि यह एक अद्वितीय Name का उपयोग करके पूरा किया जा सकता है, लेकिन मुझे आश्चर्य है कि यह बिना किया जा सकता है।एक ही प्रकार को दो बार पंजीकृत करने और केवल सिंगलटन

उदाहरण के लिए:

_container.RegisterType<Music>(new InjectionConstructor(new Album("Non-singleton", "Non-singleton"))); 
_container.RegisterType<Music>(new ContainerControlledLifetimeManager()); 

और बुला

var music = Factory.Resolve<Music>(); 

रिटर्न 'गैर-सिंगलटन' वस्तु। सबसे पहले, मैंने सोचा कि यह पंजीकरण आदेश पर आधारित था, लेकिन इसके आसपास स्विचिंग मुझे अभी भी 'गैर-सिंगलटन' उदाहरण प्राप्त हुआ है।

क्या इसके लिए कोई कारण है? ResolveName विशेषता निर्दिष्ट करने वाले एक ही कंटेनर w/out में दो पंजीकृत ऑब्जेक्ट्स के लिए केवल सिंगलटन प्रकार का कोई तरीका है?

उत्तर

21

के इसे तोड़ने के नीचे दो:

_container.RegisterType<Music>(new InjectionConstructor(
    new Album("Non-singleton", "Non-singleton"))); 

इस कंटेनर में कोई नाम के साथ प्रकार Music (शून्य या डिफ़ॉल्ट) के साथ पंजीकृत और एकता बताता निर्माता है कि एक प्रकार Album स्वीकार करता है उपयोग करने के लिए। द्वारा Music(Album album) कन्स्ट्रक्टर के मान के रूप में बनाए गए उदाहरण को हमेशा पास करने के लिए। इसलिए प्रत्येक Music इंस्टेंस में उसी एल्बम को इंजेक्शन दिया जाएगा।

_container.RegisterType<Music>(new ContainerControlledLifetimeManager()); 

यह कोई नाम (शून्य या डिफ़ॉल्ट) के साथ प्रकार Music के आधार पर एक पंजीकरण करता है। चूंकि, कोई इंजेक्शनमम्बर नहीं हैं, मौजूदा पंजीकरण में एकमात्र परिवर्तन एक आजीवन प्रबंधक जोड़ना है। मौजूदा पंजीकरण अपडेट किया गया है क्योंकि BuildKey (टाइप: संगीत, नाम: शून्य) दोनों रजिस्टर टाइप कॉल के लिए समान है।

unityContainer.RegisterType<Music>(new InjectionConstructor(new Album("Non-singleton", "Non-singleton"))); 

unityContainer.RegisterType<Music>(new ContainerControlledLifetimeManager()); 

var music = unityContainer.Resolve<Music>(); 
var music2 = unityContainer.Resolve<Music>(); 

bool areEqual = ReferenceEquals(music, music2); 

उपर्युक्त में एक्वाल सत्य है, इसलिए एक ही उदाहरण वापस किया जा रहा है।

क्या नाम प्रविष्टि निर्दिष्ट करने वाले एक ही कंटेनर w/आउट में दो पंजीकृत ऑब्जेक्ट्स के लिए केवल सिंगलटन प्रकार को हल करने का कोई तरीका है?

प्रकार प्रकार और नाम से पंजीकृत हैं तो कई पंजीकरण के लिए एक ही प्रकार एक नाम का उपयोग करने के लिए है के लिए एक ही रास्ता:

अब अगर आप पहले पंजीकरण तुम कर सकते हो ओवरराइड करने के लिए करना चाहता था कि एक नया इंजेक्शन कन्स्ट्रक्टर निर्दिष्ट करके। यह बिल्ड योजना को साफ़ करेगा और कन्स्ट्रक्टर चयन नीति सेट करेगा।

unityContainer.RegisterType<Music>(new InjectionConstructor(
    new Album("Non-singleton", "Non-singleton"))); 

unityContainer.RegisterType<Music>(new ContainerControlledLifetimeManager(), 
    new InjectionConstructor(new Album("singleton", "singleton"))); 

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

एक दिलचस्प सवाल यह है कि आप पहले रजिस्टर टाइप कॉल के बाद कन्स्ट्रक्टर चयन नीति को कैसे रीसेट करेंगे ताकि यूनिटी अपनी डिफ़ॉल्ट कन्स्ट्रक्टर चयन नीति का उपयोग करे। आप कस्टम इंजेक्शनमेम्बर के साथ ऐसा कर सकते हैं जो कन्स्ट्रक्टर चयन नीति को साफ़ करता है:

unityContainer.RegisterType<Music>(new InjectionConstructor(
    new Album("Non-singleton", "Non-singleton"))); 

unityContainer.RegisterType<Music>(new ContainerControlledLifetimeManager(), 
    new ClearInjectionConstructor()); 

public class ClearInjectionConstructor : InjectionMember 
{ 
    public override void AddPolicies(Type serviceType, 
     Type implementationType, 
     string name, 
     Microsoft.Practices.ObjectBuilder2.IPolicyList policies) 
    { 
     policies.Clear<IConstructorSelectorPolicy>(
      new NamedTypeBuildKey(implementationType, name)); 
    } 
} 
संबंधित मुद्दे