2010-10-26 7 views
19

परिदृश्य: मैं एक अलग डीएल में परिभाषित इंटरफ़ेस अनुबंध के आधार पर रनटाइम पर प्लगइन्स (निर्यात) लोड करने के लिए प्रबंधित एक्सटेंसिबिलिटी फ्रेमवर्क का उपयोग कर रहा हूं । मेरे विजुअल स्टूडियो समाधान में, मेरे पास 3 अलग-अलग प्रोजेक्ट हैं: मेजबान एप्लिकेशन, एक क्लास लाइब्रेरी (इंटरफ़ेस को परिभाषित करना - "आईपीएलयूजीन") और इंटरफ़ेस को लागू करने वाली दूसरी कक्षा लाइब्रेरी (निर्यात - "MyPlugin.dll")।MEF: "अनुरोधित प्रकारों में से एक या अधिक लोड करने में असमर्थ। अधिक जानकारी के लिए लोडर अपवादों को पुनर्प्राप्त करें"

होस्ट अपनी रूट निर्देशिका में निर्यात की तलाश करता है, इसलिए परीक्षण के दौरान, मैं पूरे समाधान का निर्माण करता हूं और प्लगइन क्लास लाइब्रेरी बिन/रिलीज फ़ोल्डर से प्लगइन.dll को मेजबान की डीबग निर्देशिका में कॉपी करता हूं ताकि होस्ट की निर्देशिकासूची मिल जाए यह और इसे कंपोज़िशनकंटर में जोड़ने में सक्षम हो। प्रत्येक पुनर्निर्माण के बाद Plugin.dll स्वचालित रूप से कॉपी नहीं होता है, इसलिए जब भी मैं अनुबंध/कार्यान्वयन में परिवर्तन करता हूं, तो मैन्युअल रूप से ऐसा करता हूं।

बहरहाल, समय के एक जोड़े मैं की नकल की हो रही है (एक अद्यतन) Plugin.dll पहले बिना मेजबान एप्लिकेशन को चलाने की है, और यह रचना के दौरान एक अपवाद फेंका गया है:

Unable to load one or more of the requested types. Retrieve the LoaderExceptions for more information

यह की है इस तथ्य के कारण कि प्लगइन.dll यह IP12ugin के विभिन्न संस्करण लागू करने से आयात करने का प्रयास कर रहा है, जहां संपत्ति/विधि हस्ताक्षर मेल नहीं खाते हैं। यद्यपि इसे नियंत्रित और निगरानी वाले वातावरण में टालना आसान है, प्लगइन फ़ोल्डर में अप्रचलित आईपीएलजिन कार्यान्वयन से बचने के लिए, मैं उत्पादन वातावरण में ऐसी धारणाओं पर भरोसा नहीं कर सकता, जहां विरासत प्लगइन्स का सामना किया जा सकता है।

समस्या यह है कि यह अपवाद पूरी तरह से समग्र रचना कार्रवाई को प्रभावित करता है और कोई निर्यात आयात किया जाता है। मैं यह पसंद करता था कि मेल नहीं खाती आईपीएलयूजीन कार्यान्वयन को अनदेखा किया जाता है, ताकि सूची में अन्य निर्यात, आईपीएलजिन के सही संस्करण को लागू करने के लिए अभी भी आयात किए जा रहे हैं।

क्या इसे पूरा करने का कोई तरीका है? मैं कई संभावित विकल्पों में से किसी में सोच रहा हूँ:

  • से पहले या जब बुला लिखें CompositionContainer पर स्थापित करने के लिए ("आयात में नाकाम रहने पर ध्यान न दें") एक झंडा नहीं है
  • वहाँ एक ऐसी ही झंडे पर निर्दिष्ट करने के लिए है <ImportMany()> विशेषता
  • एक तरीका होता है यात्रा प्रक्रिया अंतर्निहित लिखें() के लिए पर "हुक", और प्रत्येक के साथ सौदा करने में सक्षम हो (विफल) किसी भी तरह केवल लागू करने के आयात के लिए देखने के लिए हस्ताक्षर करने से मजबूत नाम का उपयोग करना आयात व्यक्तिगत रूप से
  • को वर्तमान IPlugin
  • का संस्करण

विचार?

उत्तर

15

मैंने a similar problem में भी भाग लिया है।

यदि आप सुनिश्चित हैं कि आप इस तरह के "खराब" असेंबली को अनदेखा करना चाहते हैं, तो समाधान प्रत्येक असेंबली कैटलॉग बनाने के बाद AssemblyCatalog.Parts.ToArray() पर कॉल करना है। यह आपके द्वारा उल्लेख किए गए ReflectionTypeLoadException को ट्रिगर करेगा। फिर आपको अपवाद पकड़ने और बुरी असेंबली को अनदेखा करने का मौका मिला है।

आप सभी "अच्छा" विधानसभाओं के लिए AssemblyCatalog वस्तुओं बनाया है, तो आप उन्हें एक AggregateCatalog में कुल और CompositionContainer निर्माता है कि पारित कर सकते हैं।

+0

मुझे एक नज़र आएगी। और हाँ, मुझे यकीन है कि मैं उन्हें अनदेखा करना चाहता हूं - मैं उन्हें वैसे भी उपयोग नहीं कर सकता, और वे जो भी चाहते हैं, उनके लिए वे गड़बड़ कर रहे हैं, तो यह कोई ब्रेनर नहीं है, नहीं? :) – d7samurai

+0

@ d7samurai: कुछ लोग अपवाद संदेश को गुगल करके यहां समाप्त हो जाएंगे। मैं बस उनके लिए जोर देना चाहता था कि यह त्रुटि के अंतर्निहित कारण को ठीक नहीं करता है। इसके अलावा, चुप विफलता (उर्फ "त्रुटि फिर से शुरू करें" व्यवहार) शुरू करना बिल्कुल कोई ब्रेनर नहीं है; यह बग पहचान और निदान को काफी जटिल कर सकता है। मैं कम से कम उपयोगकर्ता को कुछ संकेत देने की सलाह देता हूं कि कुछ बुरा हुआ। बेशक –

+0

। "अनदेखा" करके मेरा मतलब है "इसे पूरी आयात प्रक्रिया को रोकने के बिना आगे बढ़ना"। कोई उपयोगकर्ता नहीं है, क्योंकि यह एक विंडोज़ सेवा है, लेकिन यह सब कुछ (बूटस्ट्रैपर) लॉग होता है, दोनों सामान्य संचालन और अपवाद ("लोडर एक्सेप्शन" में सभी अपवादों को डंप करने सहित - जब यह लागू होता है)। – d7samurai

7

यह समस्या, कई कारकों (भरी हुई विधानसभाओं पर किसी भी अपवाद) के कारण हो सकता अपवाद की तरह कहते हैं, के लिए ExceptionLoader को देखो (उम्मीद) कुछ विचार

एक और समस्या/समाधान है कि मैंने पाया मिलता है, है निर्देशिकासूची का उपयोग करते समय, यदि आप दूसरा पैरामीटर "सर्चपेटर्न" निर्दिष्ट नहीं करते हैं, तो एमईएफ उस फ़ोल्डर में सभी डीएलएस लोड करेगा (तीसरे पक्ष सहित), और निर्यात प्रकारों की तलाश करना शुरू करें, जो इस समस्या का कारण बन सकते हैं, एक समाधान है कि निर्यात करने वाले सभी असेंबली पर एक सम्मेलन का नाम होना चाहिए, और निर्दिष्ट करें कि निर्देशिकासूची निर्माता में, मैं * _Plugin.dll का उपयोग करता हूं, इस तरह एमईएफ केवल असेंबली लोड करेगा होते प्रकार

निर्यात मेरे मामले MEF एक NHibernate dll लोड किया गया था और (इस त्रुटि निर्देशिका में DLLs से किसी के साथ भी हो सकता है) LoaderException पर कुछ विधानसभा संस्करण त्रुटि फेंक में, इस दृष्टिकोण

7

यहाँ समस्या हल उपरोक्त विधियों का एक उदाहरण है:

var di = new DirectoryInfo(Server.MapPath("../../bin/")); 

     if (!di.Exists) throw new Exception("Folder not exists: " + di.FullName); 

     var dlls = di.GetFileSystemInfos("*.dll"); 
     AggregateCatalog agc = new AggregateCatalog(); 

     foreach (var fi in dlls) 
     { 
      try 
      { 
       var ac = new AssemblyCatalog(Assembly.LoadFile(fi.FullName)); 
       var parts = ac.Parts.ToArray(); // throws ReflectionTypeLoadException 
       agc.Catalogs.Add(ac); 
      } 
      catch (ReflectionTypeLoadException ex) 
      { 
       Elmah.ErrorSignal.FromCurrentContext().Raise(ex); 
      } 
     } 

     CompositionContainer cc = new CompositionContainer(agc); 

     _providers = cc.GetExports<IDataExchangeProvider>(); 
+0

यह एएसपी.नेट एमवीसी के लिए काम नहीं करता है यदि आप एक अलग डोमेन का उपयोग नहीं कर रहे हैं, क्योंकि असेंबली। लोडफाइल फ़ाइल को किसी भिन्न डोमेन पर लोड करता है। इसे हल करने के लिए आपको केवल असेंबली.लोड लोड का उपयोग करने की आवश्यकता है। – Eben

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

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