2012-05-18 15 views
14

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

public interface IConfig 
{ 
    string Username { get; } 
    string Password { get; } 
    //... other settings 
} 

public class Foo : IFoo 
{ 
    private readonly string username; 
    private readonly string password; 

    public Foo(IConfig config) 
    { 
     this.username = config.Username; 
     this.password = config.Password; 
    } 
} 

नकारात्मक पक्ष यह है कि IConfig क्योंकि यह एक समग्र कॉन्फ़िग फ़ाइल से deserialised है सेटिंग्स की एक बड़ी संख्या में शामिल है, इसलिए पूरी वस्तु इंजेक्शन करना अनावश्यक है। मैं क्या करना चाहता हूं कन्स्ट्रक्टर को Foo(string username, string password) में बदलना है ताकि इसे केवल अपनी आवश्यक सेटिंग्स प्राप्त हो। यह Foo बनाने के लिए Foo ऑब्जेक्ट्स को अधिक आसान बनाने के लिए बनाता है (IConfig सेट अप करने के लिए नहीं)। मैं अपने NinjectModule में सीधे निर्माता तर्क बाध्य करने के लिए, निम्नलिखित की तरह कुछ करना चाहते हैं:

public class MyModule : NinjectModule 
{ 
    public override void Load() 
    { 
     Bind<IConfig>().To<JsonConfig>() 
      .InSingletonScope(); 

     Bind<IFoo>().To<Foo>() 
      .WithConstructorArgument("username", IConfig.Username) 
      .WithConstructorArgument("password", IConfig.Password); 
    } 
} 

जाहिर है इस कोड काम नहीं करता है, लेकिन मैं कर रहा मैं चाहता था के बारे में कैसे जाना होगा?

मेरे मूल विचार NinjectModule.Kernel उपयोग करने के लिए IKernel फिर मेरे IConfig वस्तु का एक उदाहरण के रूप में मिलता है और आवश्यक गुण इंजेक्षन प्राप्त करने के लिए गया था, लेकिन वस्तु NinjectModule.Kernel द्वारा वापस नहीं Get<T>() विधि है।

उत्तर

14

आप सही रास्ते पर हैं:

Kernel.Get<T>() विधि एक विस्तार विधि Ninject namepsace में ResolutionExtensions पर परिभाषित किया गया है ताकि using Ninject; को जोड़ने के साथ यह रूप में अच्छी तरह से अपने मॉड्यूल में उपलब्ध है।

लेकिन बजाय Module.Kernel आप IContextWithConstructorArgument के दूसरे अधिभार में प्रदान की जाती का उपयोग पाने के लिए करना चाहिए Kernel:

Bind<IFoo>().To<Foo>() 
    .WithConstructorArgument("username", 
          context => context.Kernel.Get<IConfig>().Username) 
    .WithConstructorArgument("password", 
          context => context.Kernel.Get<IConfig>().Password); 
+1

मुझे यह काम करने के लिए प्रतीत नहीं होता है। लैम्ब्डा में बनाई गई 'आईकोनफिग' ऑब्जेक्ट में सभी डिफ़ॉल्ट मान होते हैं (उन सेटिंग्स के लिए खाली तार)। अगर मैं सिर्फ एक सामान्य कर्नेल करता हूं। प्राप्त करें कि मैंने 'निनजेक्ट का उपयोग करके' जोड़ा है, यह ठीक से काम करता है। क्या मुझे 'संदर्भ' संस्करण काम करने के प्रयास को निवेश करना चाहिए, क्या कोई फायदा है? –

+0

इसे 'context. कर्नेल' के साथ काम करना चाहिए, मैं इसे देख लूंगा। 'आईकोनफिग' में मूल्यों को कैसे पिलेट किया जाता है?क्या आप एकाधिक कर्नेल का उपयोग कर रहे हैं? – nemesv

+0

बस एक साधारण परीक्षण परियोजना बनाई और यह काम करता है। मेरे विशेष समाधान के लिए कुछ विशिष्ट होना चाहिए। धन्यवाद! –

1

यह Interface segregation principle के लिए एक अच्छा candiate हो सकता है।

इस मामले में, इस तरह के एक ICredentialConfig सिर्फ Username और Password गुण युक्त के रूप में एक और इंटरफेस को परिभाषित है, तो IConfig कर इस इंटरफ़ेस को लागू।

public Interface ICredentialConfig 
{ 
    string Username { get; } 
    string Password { get; } 
} 

public Interface IConfig : ICredentialConfig 
{ 
    //... other settings 
} 

अब FooICredentialConfig बजाय IConfig पर निर्भर करते हैं। फिर आप कर सकते हैं:

  1. अपने JsonConfig सम्मिलित करें, Ninject उपयोग करने के बजाय हार्डकोडेड पैरामीटर नाम होने का।
  2. पूर्ण IConfig इंटरफ़ेस को कार्यान्वित करने के बजाय Foo को तत्काल करने के लिए ICredentialConfig लागू/नकल करें।
संबंधित मुद्दे