2012-12-26 32 views
13

मान लें कि मेरे पास निम्नलिखित वर्ग हैं जिन्हें मैं निनजेक्ट का उपयोग करके निर्माण करना चाहता हूं, निर्भरता दिखाने वाले तीरों के साथ।निंजा स्कोपिंग - पूरे ग्राफ में निर्मित एक ही उदाहरण का उपयोग करें

A > B > D 
A > C > D 

मैं Ninject ऐसे कॉन्फ़िगर करने के लिए है कि एक क्षणिक दायरे वाला है, यानी हर बार जब आप एक ए के लिए Ninject पूछना है चाहते हैं, आप एक नया बनाएँ। मैं यह भी चाहता हूं कि बी और सी क्षणिक हो जाएं, जब भी आप ए के लिए पूछते हैं, तो आप उनमें से एक नया प्राप्त करते हैं लेकिन मुझे डी दोनों बी और सी में पुन: उपयोग करने के लिए चाहते हैं, इसलिए हर बार जब मैं ए, प्रत्येक वस्तु में से एक का निर्माण करने के लिए Ninject चाहते हैं, दो डीएस नहीं। लेकिन मैं नहीं चाहता कि विभिन्न डी के रूप में डीएस का पुन: उपयोग किया जाए।

निनजेक्ट का उपयोग करके इसे स्थापित करने का सबसे अच्छा तरीका क्या है?

अद्यतन:
कुछ और अनुसंधान के बाद, ऐसा लगता है एकता जो मैं के लिए क्या देख रहा हूँ करता है एक PerResolveLifetimeManager है। क्या कोई निंजा बराबर है?

उत्तर

13

निनजेक्ट object scopes out of the box में निर्मित चार का समर्थन करता है: क्षणिक, सिंगलटन, थ्रेड, अनुरोध।

तो कोई PerResolveLifetimeManager स्कोप की तरह नहीं है लेकिन आप InScope विधि के साथ एक कस्टम स्कोप पंजीकृत करने के साथ इसे आसानी से कार्यान्वित कर सकते हैं।

जैसा कि यह निकला कि मौजूदा निदान विस्तार है: ninject.extensions.namedscope जो InCallScope विधि प्रदान करता है जो आप खोज रहे हैं।

हालांकि यदि आप इसे स्वयं करना चाहते हैं तो आप एक कस्टम InScope प्रतिनिधि के साथ कर सकते हैं। आप गुंजाइश वस्तु के रूप में उपयोग करने के लिए प्रकार A के लिए मुख्य IRequest वस्तु का उपयोग कर सकते कहाँ:

var kernel = new StandardKernel(); 
kernel.Bind<A>().ToSelf().InTransientScope(); 
kernel.Bind<B>().ToSelf().InTransientScope(); 
kernel.Bind<C>().ToSelf().InTransientScope(); 
kernel.Bind<D>().ToSelf().InScope(
    c => 
     { 
      //use the Request for A as the scope object       
      var requestForA = c.Request; 
      while (requestForA != null && requestForA.Service != typeof (A)) 
      { 
       requestForA = requestForA.ParentRequest; 
      } 
      return requestForA; 
     }); 

var a1 = kernel.Get<A>();  
Assert.AreSame(a1.b.d, a1.c.d); 

var a2 = kernel.Get<A>();  
Assert.AreSame(a2.b.d, a2.c.d); 

Assert.AreNotSame(a1.c.d, a2.c.d); 

कहाँ नमूना वर्ग हैं:

public class A 
{ 
    public readonly B b; 
    public readonly C c; 
    public A(B b, C c) { this.b = b; this.c = c; } 
} 

public class B 
{ 
    public readonly D d; 
    public B(D d) { this.d = d; } 
} 

public class C 
{ 
    public readonly D d; 
    public C(D d) { this.d = d; } 
} 

public class D { } 
+0

यदि कोई निर्भरता श्रृंखला है जिसमें ए शामिल नहीं है तो डी भी भाग नहीं लेता है? –

+0

@ केविनबैबॉक। नहीं तो यह टूट नहीं जाएगा। फिर प्रतिनिधि निम्नलिखित पंजीकरण के बराबर 'शून्य' वापस करेगा: 'कर्नेल। ()।) स्वयं()। InTransientScope(); ' – nemesv

+0

स्पष्टीकरण के लिए धन्यवाद। अच्छा उत्तर! –

1

एक वैकल्पिक निर्भरता खुद के निर्माण के लिए है।

var kernel = new StandardKernel(); 
kernel.Bind<A>().ToMethod(ctx => 
{ 
    var d = new D(); 
    var c = new C(d); 
    var b = new B(d); 
    var a = new A(b, c); 
    return a; 
}); 

यह पसंदीदा तरीका नहीं हो सकता है, लेकिन यह हमेशा B, C, और D का एक नया उदाहरण का उपयोग करते हुए (लेकिन B और C के लिए D का एक ही उदाहरण पुन: उपयोग) A का एक नया उदाहरण का निर्माण करेगी। आप InTransientScope() पर एक कॉल जोड़ सकते हैं, लेकिन यह आवश्यक नहीं है क्योंकि यह डिफ़ॉल्ट दायरा है।

+0

यह मेरी आवश्यकता के लिए बहुत विशिष्ट है। वास्तव में मेरे कोड में ए, बी, सी स्तरों पर कई अलग-अलग कक्षाएं हैं जिन्हें सभी को दिए गए रिज़ॉल्यूशन के लिए डी साझा करने की आवश्यकता है। – RationalGeek

6

मुझे अपनी विशिष्ट समस्या का समाधान मिला, जो ninject.extensions.namedscope एक्सटेंशन द्वारा प्रदान की गई इनकॉलस्कोप है। यह एकता PerResolveLifetimeManager अवधारणा के समान व्यवहार करता है।