2012-02-14 8 views
5

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

रजिस्ट्री 1 IBusinessContext, IRules, और ILogger प्रकारों के लिए सभी डिफ़ॉल्ट सेट अप करता है। यह किसी भी अन्य विशेषज्ञता के साथ इंटरफेस के साथ जेनेरिक कॉन्टेक्स्ट/लॉगर/नियमों को जोड़ रहा है।

public GenericRegistry() 
    { 
     // Set up some generic bindings here 
     For<ILogger>().Use<Loggers.GenericLogger>(); 
     For<IBusinessRule>().Use<Rules.StandardRule>(); 
     For<IBusinessContext>().Use<Contexts.GenericBusinessContext>(); 
     For<ILoggerContext>().Use<Loggers.GenericLoggerContext>(); 
    } 

रजिस्ट्री 2 सेट अप IBusinessContext SpecialisedContext वर्ग का उपयोग करें और ctor SpecializedLogger उपयोग करने के लिए कहता है करने के लिए। IBusinessContext के लिए उदाहरण "SpecialContext" नाम दिया गया है।

public SpecializedRegistry() 
    { 
     // Old style syntax as it affects the default for IBusinessContext 
     // Perhaps a hint at what I'm doing? 
     InstanceOf<IBusinessContext>().Is.OfConcreteType<Contexts.SpecializedBusinessContext>().Named(SpecializedInstanceName).Ctor<ILogger>().Is<Loggers.SpecialisedLogger>(); 
    } 

यह सभी संरचना मानचित्र (पुराने या नए वाक्यविन्यास के आधार पर) में अपेक्षित काम करता है।

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

तो ... क्या मैं सिर्फ आईओसी अवधारणा का गलत उपयोग कर रहा हूं, मेरी शीर्ष स्तर की वस्तु को नाम से पूछने की उम्मीद कर रहा हूं या क्या मैं ऐसा करने का एक बेहतर तरीका हूं जो मैं करने की कोशिश कर रहा हूं? क्या मुझे इसके बजाय एमईएफ की तरह कुछ इस्तेमाल करना चाहिए और प्लग-इन की तरह यह सब इलाज करना चाहिए?

मुझे तनाव है कि मैं इसे एक गूंगा कारखाने की तरह उपयोग नहीं कर रहा हूं और कंटेनर से टाइप एक्स के उदाहरण के लिए कोड के प्रत्येक स्तर पर पूछ रहा हूं, यह केवल आरंभिक कार्य है।

अपना समय के लिए अग्रिम धन्यवाद और मदद :)

उत्तर

3

सब उस नाम से Ninject बाइंडिंग की स्थापना, कि यदि प्राप्त करने के लिए यह क्या आप IMO की जरूरत है एक ही रास्ता है के साथ गलत कुछ भी नहीं है।

तो बुनियादी वाक्य रचना है:

Bind<IBusinessContext>().To<ConcreteBusinessContext>().Named("XYZ"); 

या यदि आप एक अलग बाध्यकारी प्राप्त करने के लिए एक विशिष्ट बुला वर्ग की जरूरत है तो आप की कोशिश कर सकते हैं:

Bind<IIBusinessContext>().To<SomeOtherConcreteBusinessContext>().WhenInjectedInto<TypeOfCallingClass>(); 

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

Bind<Func<string, IBusinessContext>>().ToMethod(ctx => str => DetermineWhichConcreteTypeToLoad(ctx, str)); 

//messy sudo code 
static DetermineWhichConcreteTypeToLoad(IContext ctx, string str) 
{ 
    if(str == "somevalue"){ 
     return ctx.Kernel.Get<ConcreteType1>(); 
    else 
     return ctx.Kernel.Get<ConcreteType2>(); 
} 

और अपने बुला वर्ग कुछ ऐसी दिखाई देगी तरह:

class DoStuff 
{ 
    Func<string, IBusinessContext>> contextFunc; 

    DoStuff(Func<string, IBusinessContext>> contextFunc) 
    { 
     this.contextFunc = contextFunc; 
    } 

    void SomeMethod() 
    { 
     var configuredValue = GetConfiguredValueSomehow(); 
     var context = contextFunc(configuredValue); //<-- this passes your config value back to ninject in the ToMethod() lambda 
     //do something with context 
    } 
} 

कि उदाहरण में नामित उदाहरण के लिए कोई जरूरत नहीं है, जैसा कि आप एक तरीका है जिसके विशिष्ट ठोस प्रकार लोड करता है, फिर भी आप अभी भी अगर उदाहरणों नामित उपयोग कर सकते हैं

Bind<IBusinessContext>().To<ConcreteBusinessContext>().Named("config1"); 
Bind<IBusinessContext>().To<SomeOtherBusinessContext>().Named("config2"); 

Bind<Func<string, IBusinessContext>>().ToMethod(ctx => str => ctx.Kernel.Get<IBusinessContext>().Named(str)); 

class DoStuff 
{ 
    Func<string, IBusinessContext>> contextFunc; 

    DoStuff(Func<string, IBusinessContext>> contextFunc) 
    { 
     this.contextFunc = contextFunc; 
    } 

    void SomeMethod() 
    { 
     var configuredValue = "config1"; 
     var context = contextFunc(configuredValue); //<-- this will passthrough "config1" to the above ToMethod() method and ask for a IBusinessContext named "config1" 

    } 
} 

संपादित करें: आप इस तरह कुछ करना चाहता हूँ मुझे लगता है कि आपके config मूल्य does not को बुला कोड से आया है, तब यह बातें बहुत आसान बना देता है उल्लेख करना भूल गया। आपका कोड के बजाय कुछ की तरह लग सकता है:

// this method can just be a global method in you app somewhere 
static string GetConfigValue() 
{ 
    //something like 
    return AppSetting.Get("config"); 
} 

Bind<IBusinessContext>().To<ConcreteBusinessContext>().When(r => GetConfigValue() == "config1"); 
Bind<IBusinessContext>().To<SomeOtherBusinessContext>().When(r => GetConfigValue() == "config2"); 

class DoStuff 
{ 
    IBusinessContext context; 

    DoStuff(BusinessContext context) 
    { 
     this.context = context; 
    } 

    void SomeMethod() 
    { 
     //use the context value as you normally would 
    } 
} 

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

+0

धन्यवाद हारून! यह मेरे लिए कुछ चीजों को मंजूरी दे दी है :) यह बहुत सराहना की है। – NoodleAwa