2012-03-22 8 views
5

मैं निम्नलिखित कोड है: निर्माता इंजेक्शन के साथएक वर्ग को कैसे पंजीकृत करें जिसमें 'Func <>' पैरामीटर के रूप में है?

_container = new UnityContainer(); 
_container.RegisterType<IDownloader, Downloader>(); 
_container.RegisterType<INewObject, NewObject>(); 
_container.RegisterType<SearchViewModel>(); 

SearchViewModel वर्ग:

class SearchViewModel 
{ 
    private readonly Func<IDownloader> _downloaderFactory; 
    private readonly INewObject _newObject; 
    private IDownloader _downloader; 

    public SearchViewModel(Func<IDownloader> downloaderFactory, INewObject newObject) 
    { 
     _downloaderFactory = downloaderFactory; 
     _newObject = newObject; 
    }   
} 

प्रश्न: कैसे SearchViewModel है कि Fun<> पैरामीटर के रूप में रजिस्टर करने के लिए?

_container.RegisterType<SearchViewModel>(new InjectionConstructor(DownloaderFactory())); 

कोड ऊपर केवल INewObject बिना काम करता है।

लक्ष्य: InjectionConstructor साथ हल कारखाने और स्वचालित रूप से INewObject, INewObject2, INewObject3 हल (जैसे पैरामीटर के बिना: RegisterType<SearchViewModel>())।

क्या यह संभव है? शायद वैकल्पिक?

public interface IDownloaderFactory 
{ 
    IDownloader Create(); 
} 

तो फिर तुम कारखाने कि बस उदाहरणों को हल करने के लिए फिर कंटेनर का उपयोग करता प्रतिनिधित्व करने के लिए एक वर्ग बनाने के लिए:

+1

आप इनवॉब्जेक्ट पैरामीटर के लिए सेटर इंजेक्शन का उपयोग क्यों नहीं करते? – daryal

+0

Func पर निर्भर करने के लिए आप SearchViewModel क्यों बनाते हैं? क्या यह रिसाव अमूर्त नहीं है? मुझे लगता है कि आपको सीधे आईडीउनलोडर इंटरफेस इंजेक्ट करना चाहिए। IDownloader का कंक्रीट कार्यान्वयन कारखाने के व्यवहार को समाहित कर सकता है। यहां कोड नमूना देखें: http://stackoverflow.com/questions/9757953/can-any-of-existing-ioc-containers-create-the-lazy-proxy-classes- गतिशील रूप से –

उत्तर

8

मैं इस समस्या का समाधान कर लिया:

_container.RegisterType<Func<IDownloader>>(new InjectionFactory(i => 
      new Func<IDownloader> (() => _container.Resolve<IDownloader>()))); 
_container.RegisterType<SearchViewModel>(); 

नया समारोह, एक प्रमुख कारण यह है इससे पहले कि मैं करने की कोशिश की:

_container.RegisterType<Func<IDownloader>>(new InjectionFactory(i => 
      _container.Resolve<IDownloader>())); 

इसके अलावा IDownloaderFactory बजाय Func<IDownloader> downloaderFactory उपयोग करने के लिए बेहतर तरीका। IDownloaderFactory प्रतिनिधि को समाहित कर सकता है।

यह भी मुझे लगता है कि एक प्रतिनिधि का उपयोग कारखाने के अंदर निर्भरता के रूप में टूटा संरचना रूट से बेहतर समाधान है।

2

यहाँ उपयोग करने के लिए आम तौर पर स्वीकार पैटर्न एक सार कारखाना घोषित करने और इसे थोड़ा और अधिक स्पष्ट बनाने के लिए है:

public class DownloaderFactory : IDownloaderFactory 
{ 
    private UnityContainer _Container; 
    public DownloaderFactory(UnityContainer container) 
    { 
     this._Container = container; 
    } 

    public IDownloader Create() 
    { 
     return this._Container.Resolve<IDownloader>(); 
    } 
} 

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

class SearchViewModel 
{ 
    private readonly IDownloaderFactory _downloaderFactory; 
    private readonly INewObject _newObject; 

    public SearchViewModel(IDownloaderFactory downloaderFactory, INewObject newObject) 
    { 
     _downloaderFactory = downloaderFactory; 
     _newObject = newObject; 

     Console.WriteLine(downloaderFactory.Create().GetHashCode()); 
     Console.WriteLine(downloaderFactory.Create().GetHashCode()); 
    } 

}

अब आप इसे देख सकते हैं बस काम करता है और हर बार नया उदाहरणों पैदा करता है।

कंटेनर की स्थापना इस प्रकार दिखाई देगा:

 var container = new UnityContainer(); 
     container.RegisterType<IDownloader, Downloader>(); 
     container.RegisterType<INewObject, NewObject>(); 
     container.RegisterType<IDownloaderFactory, DownloaderFactory>(); 
     container.RegisterType<SearchViewModel>(); 
     container.RegisterInstance(container); 
     var model = container.Resolve<SearchViewModel>(); 

सूचना है कि आप कंटेनर आप इतना है कि कारखाने इस विधि या एक ThreadLocal का उपयोग कर एक ही उदाहरण या तो हो जाता है के साथ काम कर रहे हैं के कहने रजिस्टर करने की आवश्यकता इंस्टेंसिंग या कुछ।

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