2012-11-03 27 views
7

पर निंजा संपत्ति इंजेक्शन ninject का उपयोग करके मैं संपत्ति को इंजेक्ट करने का प्रयास कर रहा हूं। ninject मॉड्यूल में दो बाइंडिंग को देखते हुए, मैं ConcreteDependency को B में इंजेक्शन देने की अपेक्षा करता हूं।
हालांकि, ऐसा लगता है कि WhenInjectedInto इस प्रकार के लक्ष्य को घोषित करने के प्रकार को अस्वीकार नहीं करता है (इस मामले में संपत्ति)।बेस क्लास

क्या मुझे अपेक्षित व्यवहार प्राप्त करने का कोई तरीका है?

static void Main(string[] args) 
{ 
    var kernel = new StandardKernel(new TestModule()); 
    var b = kernel.Get<B>(); 
    var c = kernel.Get<C>(); 
} 

class TestModule : NinjectModule 
{ 
    public override void Load() 
    { 
     Bind<IDependency>().To<EmptyDependency>(); 
     Bind<IDependency>().To<ConcreteDependency>().WhenInjectedInto<B>(); 
    } 
} 

abstract class A 
{ 
    [Inject] 
    public IDependency Dependency { get; set; } 
} 

class B : A {} 

class C : A {} 

interface IDependency {} 

class EmptyDependency : IDependency { } 

class ConcreteDependency : IDependency { } 
+0

आप ए इंजेक्ट में ए, बी और सी कैसे पंजीकृत करते हैं? –

+0

आपको निनजेक्ट में नहीं होना है। चूंकि 'बी' और' सी 'ठोस वर्ग हैं इसलिए उन्हें स्पष्ट रूप से पंजीकृत होने की आवश्यकता नहीं है। – Gibsnag

उत्तर

4

एक ठोस प्रकार के खिलाफ जांच करने के लिए, आप इंटरफ़ेस पर ParentContext.Plan.Type का उपयोग कर सकते हैं। यह आपको WhenInjectedInto से अपेक्षित व्यवहार देना चाहिए। उदाहरण के लिए:

When(req => req.ParentContext.Plan.Type == typeof(B)) 
8

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

abstract class A 
    { 
     public IDependency Dependency { get; private set; } 

     public A (IDependency dependency) 
     { 
      Dependency = dependency; 
     } 

    } 

    class B : A 
    { 
     public B (IDependency dependency) 
      : base(dependency) 
     { 

     } 
    } 

    class C : A 
    { 
     public C (IDependency dependency) 
      : base(dependency) 
     { 

     } 
    } 

    interface IDependency { } 

    class EmptyDependency : IDependency { } 

    class ConcreteDependency : IDependency { } 

कॉन्फ़िगरेशन आपके जैसा ही होगा। निम्नलिखित परीक्षण में सफ़ल

[Test] 
    public void TestSpecificBindingToObjectB() 
    { 
     var kernel = new StandardKernel(new TestModule()); 
     var b = kernel.Get<B>(); 
     var c = kernel.Get<C>(); 

     Assert.AreNotEqual(b.Dependency.GetType(), c.Dependency.GetType()); 
     Assert.AreEqual(typeof(ConcreteDependency), b.Dependency.GetType()); 
    } 

आप डिफ़ॉल्ट कार्यान्वयन के साथ एक वैकल्पिक निर्भरता है और आप Inject विशेषता के साथ अपनी कक्षाओं को सजाने ठीक लगता है, आप माता-पिता के बारे में जानकारी के अनुरोध से, इस तरह खींच सकते हैं कर सकते हैं:

class TestModule : NinjectModule 
{ 
    public override void Load() 
    { 
     Bind<IDependency>().To<EmptyDependency>(); 
     Bind<IDependency>().To<ConcreteDependency>().When(req =>req.ParentContext.Request.Service == typeof(B)); 
    } 
} 

फिर ऊपर दिया गया एक ही परीक्षण संपत्ति इंजेक्शन के साथ आपके वर्ग पदानुक्रम के लिए गुजरता है।

+1

धन्यवाद, लेकिन दुर्भाग्य से मैं इसे संपत्ति इंजेक्शन के लिए काम करना चाहता हूं। निर्भरता, इस मामले में, कुछ ऐसा है जो उचित डिफ़ॉल्ट मान (खाली निर्भरता) हो सकता है, इसलिए मैं इसे बहुत से कन्स्ट्रक्टर पैरामीटर से बचने के लिए प्रोजेक्टर इंजेक्शन से कन्स्ट्रक्टर इंजेक्शन से ले जा रहा था। – Gibsnag

+1

मैंने एक अनुमान के साथ 'कब' एक्सटेंशन विधि का उपयोग करने का प्रयास किया जो कि संपत्ति के घोषित प्रकार के बजाय इंजेक्शन के प्रकार का उपयोग करेगा, लेकिन 'IRequest' से आवश्यक जानकारी प्राप्त करने के तरीके को कैसे काम नहीं कर सका। – Gibsnag

+0

मैंने डिफ़ॉल्ट उत्तरदायित्व –

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