2011-01-17 10 views
6

मैं एकता कंटेनर में एक अजीब व्यवहार देख रहा हूं, जब दो इंटरफेस के साथ काम करते हैं, तो दोनों एक ही सजावटी के लिए पंजीकरण करते हैं। एक कोड उदाहरण स्पष्ट होगा।एकता: दो इंटरफेस के लिए एक ही प्रकार का पंजीकरण

मैं निम्नलिखित वर्ग पदानुक्रम है:

public interface IBaseInterface 
    { 

    } 

    public interface IInterface1: IBaseInterface 
    { 

    } 
    public interface IInterface2: IBaseInterface 
    { 

    } 
    public class Interface1Impl : IInterface1 
    { 
    } 
    public class Interface2Impl : IInterface2 
    { 
    } 

    public class BaseInterfaceDecorator: IInterface1,IInterface2 
    { 
     private readonly IBaseInterface baseInterface; 

     public BaseInterfaceDecorator(IBaseInterface baseInterface) 
     { 
      this.baseInterface = baseInterface; 
     } 
    } 

    public class MyClass 
    { 
     private readonly IInterface1 interface1; 

     public MyClass(IInterface1 interface1) 
     { 
      this.interface1 = interface1; 
     }    
    } 

और यह पंजीकरण कोड है:

var container = new UnityContainer();   
     container.RegisterType<IInterface1, BaseInterfaceDecorator>(
      new InjectionConstructor(
       new ResolvedParameter<Interface1Impl>())); 

     container.RegisterType<IInterface2, BaseInterfaceDecorator>(
      new InjectionConstructor(
       new ResolvedParameter<Interface2Impl>())); 


     var dependency = container.Resolve<MyClass>(); 

जब MyClass को हल करने मैं Interface2Impl बजाय Interface1Impl के साथ एक BaseInterfaceDecorator हो रही है। मुझे अजीब लग रहा है। क्या तुम समझा सकते हो?

उत्तर

9

यह किसी दिए गए "टू" प्रकार के जीत के लिए अंतिम इंजेक्शन निर्देश की तरह दिखता है। यदि आप Reflector की एक प्रतिलिपि लेते हैं और UnityContainer.RegisterType (टाइप, टाइप, स्ट्रिंग, लाइफटाइम मैनेजर, इंजेक्शनमेन []) कार्यान्वयन पर एक नज़र डालें, तो आप देखेंगे क्यों।

आईएमओ, यह व्यवहार एक बग है। कम से कम, इंजेक्शनमेम्बर। कॉन्फिगर इंजेक्शनफोर (टाइप, स्ट्रिंग, इंजेक्शनमेन []) को पिछले इंजेक्शन कॉन्फ़िगरेशन को चुपचाप बदलने के बजाय अपवाद फेंकना चाहिए। हालांकि, यह वास्तव में आप जो प्रयास कर रहे हैं उसका समर्थन करना चाहिए।

+0

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

2

मुझे नहीं पता कि यह मदद करता है या नहीं। अब तक आपके लिए बहुत देर हो चुकी है। लेकिन, यदि आप नामित पंजीकरण का उपयोग करते हैं, तो यह प्राप्त करने योग्य है, यानी आप प्रत्येक प्रकार को एक अलग नाम से हल करने के लिए पंजीकृत करते हैं।

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

Container.RegisterType<IInterface1, BaseInterfaceDecorator>("interface1"); 
Container.RegisterType<IInterface2, BaseInterfaceDecorator>("interface2"); 
+0

यह एक वैध कामकाज है, लेकिन यह पंजीकरण में कॉन्वेंट प्रकारों का उपयोग करने के उद्देश्य को हरा देता है। एकता यह धारणा बनाती है कि 'टीटीओ' के लिए सभी संकल्प एक टीटीओ उदाहरण बनाने के लिए समान कॉन्फ़िगरेशन/निर्देशों का संदर्भ लेते हैं। इस प्रकार, आपको इंजेक्शन पैरामीटर्स और लाइफटाइम मैनेजमेंट के साथ समस्याएं दिखाई देगी जहां टीएफआरओ की पहचान अलग-अलग व्यवहार (विभिन्न इंजेक्शन पैरा, अलग-अलग जीवनकाल प्रबंधक इत्यादि) के परिणामस्वरूप होनी चाहिए। –

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