2012-05-22 15 views
7

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

संविदा
वेब
BingTranslator
GoogleTranslator

संविदाITranslate इंटरफ़ेस शामिल हैं: मैं चार परियोजनाओं (DLL फ़ाइलें) के साथ एक समाधान बनाया। जैसा कि नाम लागू होता है, इसमें केवल अनुबंध (इंटरफेस) होंगे, इस प्रकार निर्यातक और आयातक इसका उपयोग कर सकते हैं।

public interface ITranslator 
{ 
    string Translate(string text); 
} 

BingTranslator और GoogleTranslator इस अनुबंध के दोनों निर्यातकों हैं। वे दोनों इस अनुबंध को लागू करते हैं और विभिन्न अनुवाद सेवाओं (निर्यात) को प्रदान करते हैं (बिंग से एक, Google से दूसरा)।

[Export(typeof(ITranslator))] 
public class GoogleTranslator: ITranslator 
{ 
    public string Translate(string text) 
    { 
     // Here, I would connect to Google translate and do the work. 
     return "Translated by Google Translator"; 
    } 
} 

और BingTranslator है:

[Export(typeof(ITranslator))] 
public class BingTranslator : ITranslator 
{ 
    public string Translate(string text) 
    { 
     return "Translated by Bing"; 
    } 
} 

अब, मेरी वेब परियोजना में, मैं बस, उपयोगकर्ता से पाठ मिलता है उन अनुवादकों में से एक (बिंग और गूगल के साथ यह अनुवाद करना चाहते हैं), और परिणाम को वापस उपयोगकर्ता को वापस कर दें। इस प्रकार मेरे वेब एप्लिकेशन में, मैं एक अनुवादक पर निर्भर हूं।

public class GeneralController : Controller 
{ 
    [Import] 
    public ITranslator Translator { get; set; } 

    public JsonResult Translate(string text) 
    { 
     return Json(new 
     { 
      source = text, 
      translation = Translator.Translate(text) 
     }); 
    } 
} 

और पहेली के अंतिम टुकड़ा (छोटे टुकड़ों से समग्र गीत की रचना करने के) एक साथ इन घटकों (भागों) गोंद के लिए किया जाना चाहिए: इसलिए, मैं एक नियंत्रक इस तरह से बना लिया है। तो, वेब परियोजना के Application_Start में, मेरे पास है: जिसमें

 var parts = new AggregateCatalog 
      (
       new DirectoryCatalog(Server.MapPath("/parts")), 
       new DirectoryCatalog(Server.MapPath("/bin")) 
      ); 
     var composer = new CompositionContainer(parts); 
     composer.ComposeParts(); 

/parts फ़ोल्डर मैं कहाँ छोड़ GoogleTranslator.dll और BingTranslator.dll फ़ाइलें (निर्यातकों इन फ़ाइलों में स्थित हैं) है , और /bin फ़ोल्डर में मेरे पास बस Web.dll फ़ाइल है जिसमें आयातक शामिल है। हालांकि, मेरी समस्या यह है कि, एमईएफ आवश्यक अनुवादक के साथ GeneralController की Translator संपत्ति को पॉप्युलेट नहीं करता है। मैंने इस साइट पर एमईएफ से संबंधित लगभग हर प्रश्न को पढ़ा, लेकिन मुझे पता नहीं चला कि मेरे उदाहरण में क्या गलत है। क्या कोई मुझे बता सकता है कि मैंने यहां क्या याद किया है?

उत्तर

9

ठीक आप है क्या करने की जरूरत

public class GeneralController : Controller 
{ 
    [Import] 
    public ITranslator Translator { get; set; } 

    public JsonResult Translate(string text) 
    { 
     var container = new CompositionContainer(
     new DirectoryCatalog(Path.Combine(HttpRuntime.BinDirectory, "Plugins"))); 
     CompositionBatch compositionBatch = new CompositionBatch(); 
     compositionBatch.AddPart(this); 
     Container.Compose(compositionBatch); 

     return Json(new 
     { 
      source = text, 
      translation = Translator.Translate(text) 
     }); 
    } 
} 

मैं MEF में कोई विशेषज्ञ हूँ, और मैं क्या उपयोग के लिए खुलकर होने के लिए (प्रदर्शन के लिए विहित बिना, यह सिर्फ यह काम कर रहा है देखने के लिए है) इसके लिए, यह मेरे लिए बहुत कुछ नहीं करता है क्योंकि मैं केवल डीएलएल लोड करने के लिए इसका उपयोग करता हूं और फिर मेरे पास निर्भरता इंजेक्शन पर प्रवेश बिंदु होता है और तब से मैं डी कंटेनर का उपयोग करता हूं और एमईएफ नहीं।

MEF जरूरी है - जहाँ तक मैं देखा है। आपके मामले में, आप की जरूरत है सक्रिय रूप क्या आप MEFed करने की आवश्यकता रचना है, यानी अपने नियंत्रकतो आपके नियंत्रक कारखाने को आपके नियंत्रक उदाहरण लिखने की आवश्यकता है।

के बाद से मैं शायद ही कभी मेरी MVC अनुप्रयोग में MEFed घटकों का उपयोग, मैं MEF की आवश्यकता होती है उन कार्यों के लिए एक फिल्टर है (बजाय मेरी नियंत्रक Facrory में अपने सभी नियंत्रकों MEFing की):

public class InitialisePluginsAttribute : ActionFilterAttribute 
{ 
    public override void OnActionExecuting(ActionExecutingContext filterContext) 
    { 
     CompositionBatch compositionBatch = new CompositionBatch(); 
     compositionBatch.AddPart(filterContext.Controller); 
     UniversalCompositionContainer.Current.Container.Compose(
      compositionBatch); 
     base.OnActionExecuting(filterContext); 
    } 
} 

यहाँ UniversalCompositionContainer.Current.Container एक सिंगलटन है कंटेनर मेरी निर्देशिका कैटलॉग के साथ शुरू किया।


MEF

MEF पर मेरा व्यक्तिगत देखने के लिए, जबकि एक डि ढांचे, यह उस का एक बहुत है। इस प्रकार, डीआई और के साथ एक बड़ा ओवरलैप है यदि आप पहले ही डी फ्रेमवर्क का उपयोग करते हैं, तो वे को टकरा सकते हैं।

एमईएफ रनटाइम में डीएलएल लोड करने में शक्तिशाली है, खासकर जब आपके पास WPF ऐप है जहां आप प्लगइन लोड/अनलोड कर रहे हों और अन्य सभी चीज़ों को काम करने/सुविधाओं को हटाने की अपेक्षा करें।

एक वेब ऐप के लिए, यह बहुत समझ में नहीं आता है, क्योंकि आप वास्तव में एक काम कर रहे वेब एप्लिकेशन में डीएलएल छोड़ना नहीं चाहते हैं। इसलिए, इसका उपयोग बहुत सीमित है।

मैं एएसपी.नेट एमवीसी में प्लगइन पर एक पोस्ट लिखने जा रहा हूं और इस पोस्ट को एक लिंक के साथ अपडेट कर दूंगा।

+0

@ एलीओस्टैड का उत्तर देने के लिए धन्यवाद, लेकिन स्पष्ट रूप से मुझे समझ में नहीं आया कि मैं अपने 'ट्रांसलेटर' संपत्ति पर '[आयात]' काम करने के लिए क्या करना चाहिए। –

+0

@ सईदनेमाती ओके, मैंने यह दिखाने के लिए अद्यतन किया है कि इसका उपयोग कैसे किया जाए। – Aliostad

+3

ठीक है, यहां आपके विचार के लिए समकक्ष है - एमईएफ .NET का हिस्सा है और अपने आप में एक बहुत अच्छा डी ढांचा है। किसी अन्य का उपयोग अधिकांश मामलों में उचित नहीं है और केवल लाभ के बिना किसी अन्य तकनीक का परिचय देता है (यानी रखरखाव मूल्य नकारात्मक)। केवल एमईएफ का उपयोग कर 18 महीने की परियोजना पूरी की;) काफी अच्छा काम किया। – TomTom

2

जैसा कि @ एलोस्टाड ने उल्लेख किया है, आपको रचना के निर्माण के दौरान नियंत्रक निर्माण के दौरान/उसके बाद चलने वाली रचना प्रारंभिक कोड की आवश्यकता होती है - बस इसे वैश्विक.एक्सएक्स फ़ाइल में काम नहीं करेगा।

हालांकि, आपको केवल [Import] के बजाय [ImportMany] का उपयोग करने की आवश्यकता होगी, क्योंकि आपके उदाहरण में आप बाइनरी से प्राप्त किसी भी प्रकार के इट्रांसलेटर कार्यान्वयन के साथ काम कर सकते हैं। मुद्दा यह है कि यदि आपके पास ITranslator हैं, लेकिन उन्हें एक ही उदाहरण में आयात कर रहे हैं, तो आपको एमईएफ से अपवाद मिलेगा क्योंकि यह नहीं पता होगा कि आप वास्तव में कौन सा कार्यान्वयन चाहते हैं।

बजाय आप का उपयोग करें:

[ImportMany] 
public IEnumerable<ITranslator> Translator { get; set; } 

त्वरित उदाहरण:

http://dotnetbyexample.blogspot.co.uk/2010/04/very-basic-mef-sample-using-importmany.html

5

MEF केवल वस्तुओं जो यह अपने आप का निर्माण पर आयात बस जाएँगे। एएसपी.नेट एमवीसी के मामले में, यह एएसपी.नेट है जो नियंत्रक वस्तुओं को बनाता है। यह [Import] विशेषता को पहचाना नहीं जाएगा, इसलिए आप देखते हैं कि निर्भरता गुम है। [Export] साथ

  1. मार्क नियंत्रक वर्ग में ही:

    MEF नियंत्रकों का निर्माण करने के लिए, आप निम्नलिखित क्या करना है।

  2. एक IDependencyResolver कार्यान्वयन लागू करें जो एमईएफ कंटेनर को लपेटता है। आप एक मिलान निर्यात के लिए एमईएफ कंटेनर पूछकर GetService लागू कर सकते हैं। आप अनुरोधित प्रकार से AttributedModelServices.GetContractName के साथ एक एमईएफ अनुबंध स्ट्रिंग उत्पन्न कर सकते हैं।
  3. में DependencyResolver.SetResolver पर कॉल करके उस रिज़ॉल्वर को पंजीकृत करें।

आपको एक ही उदाहरण को कई अनुरोधों में पुन: उपयोग करने से रोकने के लिए शायद अपने अधिकांश निर्यात किए गए हिस्सों को [PartCreationPolicy(CreationPolicy.NonShared)] के साथ चिह्नित करने की आवश्यकता है। आपके एमईएफ भागों में रखा गया कोई भी राज्य अन्यथा दौड़ की स्थिति के अधीन होगा।

संपादित करें: यह blog post पूरी प्रक्रिया का एक अच्छा उदाहरण है।

संपादित 2: एक और समस्या हो सकती है। एमईएफ कंटेनर किसी भी IDisposable ऑब्जेक्ट के संदर्भों को संदर्भित करेगा, ताकि कंटेनर का निपटारा होने पर यह उन वस्तुओं को निपटान कर सके। हालांकि, यह "प्रति अनुरोध" जीवनकाल वाले वस्तुओं के लिए उपयुक्त नहीं है! IDisposable को लागू करने वाली किसी भी सेवा के लिए आपके पास प्रभावी रूप से मेमोरी रिसाव होगा।

AutoFac जैसे विकल्प का उपयोग करना संभवतः आसान है, जिसमें ASP.NET MVC integration के लिए NuGet पैकेज है और जिसमें per-request lifetimes के लिए समर्थन है।

+1

+1। एमईएफ को डी फ्रेमवर्क के रूप में डिजाइन नहीं किया गया था, इसलिए डीआई के लिए इसका उपयोग इतना जटिल है - मूल रूप से वीएस प्लगइन्स के लिए विकसित किया गया है। प्रकार उदाहरण पास करके सभी डी फ्रेमवर्क समर्थन सेवा स्थान। – Aliostad

+0

@Aliostad: यह पता चला है कि यह वास्तव में एक समस्या नहीं है क्योंकि एमईएफ अनुबंध वास्तव में तार हैं जो आप स्वयं को इस प्रकार से उत्पन्न कर सकते हैं। मैं अपना जवाब अपडेट करूंगा। –

+0

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

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