2012-02-07 16 views
6

मैं रनटाइम (SerializationException for dynamically loaded Type) पर लोड कुछ डीएल की असेंबली को हल करते समय अपवादों को संभालने के लिए AppDomain.AssemblyResolve ईवेंट का उपयोग करने का प्रयास कर रहा हूं।AppDomain.Assembly के साथ काम करना

जब घटना निकाल दिया जाता है, मैं अपनी निर्देशिका में सभी DLLs लोड और एक Assembly सारिणी निर्मित, तो मैं इस विधि का उपयोग प्रकार युक्त Assembly पाने के लिए मैं निर्दिष्ट करें:

public static Assembly GetAssemblyContainingType(String completeTypeName, Assembly[] assemblies) 
    { 
     Assembly assembly = null; 

     foreach (Assembly currentassembly in assemblies) 
     { 
      Type t = currentassembly.GetType(completeTypeName, false, true); 
      if (t != null) 
      { 
       assembly = currentassembly; 
       break; 
      } 
     } 

     return assembly; 
    } 

समस्या यह है कि है कोड केवल AssemblyQualifiedName के साथ काम करता है, और घटना द्वारा प्रदत्त ResolveEventArgs.Name इतना उपयोगी नहीं है।

क्या आप मुझे कुछ कामकाज सुझा सकते हैं?

वहाँ जब यह सक्रिय किए जाने पर इस घटना के लिए कुछ अन्य तर्क पारित करने के लिए एक तरीका है? अपने ज्ञात निर्देशिका से विधानसभाओं के साथ, इस तरह

private readonly IDictionary<string,Assembly> additional = 
    new Dictionary<string,Assembly>(); 

लोड इस शब्दकोश:

उत्तर

12

आप विधानसभाओं का एक शब्दकोश अपने निर्देशिका से, इस तरह परिभाषित कर सकते हैं

foreach (var assemblyName ... corresponding to DLL names in your directory...) { 
    var assembly = Assembly.Load(assemblyName); 
    additional.Add(assembly.FullName, assembly); 
} 

एक कार्यान्वयन प्रदान करें हुक के लिए ...

private Assembly ResolveAssembly(Object sender, ResolveEventArgs e) { 
    Assembly res; 
    additional.TryGetValue(e.Name, out res); 
    return res; 
} 

... और इसे घटना तक हुक करें:

AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve += ResolveAssembly; 
AppDomain.CurrentDomain.AssemblyResolve += ResolveAssembly; 

यह चाल चलाना चाहिए।

+5

असेंबली को प्रीलोड नहीं करना असेंबली रीसोल्व इवेंट हैंडलर की आवश्यकता को रोकता है? –

+2

@ माइकज़ जहां तक ​​मुझे पता है, 'असेंबली.लोड (असेंबलीनाम)' का उपयोग करके एक असेंबली लोड करना स्वचालित रूप से इसे आपके एप्लिकेशन डोमेन के असेंबली रिज़ॉल्यूशन कोड पर उपलब्ध नहीं करता है (जब तक वह कोड डिफ़ॉल्ट रिज़ॉल्यूशन का उपयोग करके असेंबली तक नहीं पहुंच सकता प्रक्रिया)। यह कोड एक कार्य प्रणाली से उठाया गया है (मैंने एरर हैंडलिंग कोड हटा दिया है, उदाहरण के लिए 'अतिरिक्त .ryGetValue (e.Name, out res)' कॉल को थोड़ा सा सरल बनाने के लिए कॉल करें)। जब मैं 'ResolveAssembly' हुक निकालने के लिए, मेरे कार्य प्रणाली काम कर रही :) – dasblinkenlight

+2

आप शब्दकोश के निर्माण कर रहे हैं, AssemblyName.GetAssemblyName का उपयोग () Assmebly.Load के बजाय फ़ाइल नाम की मैपिंग के विधानसभा नाम पाने के लिए और बिना शर्त से बचने के बंद हो जाता है सभी विधानसभाओं को लोड करना। –

0

आप विधानसभाओं कि आप किस प्रकार deserialize की योजना बना रहे हो सकती है सूची पता है यह बेहतर हो सकता है बस क्रमबद्धता करने से पहले लोड पूर्व सभी विधानसभाओं के लिए।

जब AssemblyResolve घटना निकाल दिया जाता है के बारे में आप किस प्रकार का लोड की वजह से कोई जानकारी नहीं है, लेकिन केवल विधानसभा नाम। यह स्पष्ट नहीं है कि आप इस मामले में किसी विशेष प्रकार से असेंबली क्यों देखेंगे।

ध्यान दें कि यदि 2 विधानसभाओं में एक ही पहचान होती है (यानी गैर-दृढ़ता से हस्ताक्षरित मामले में फ़ाइल का नाम) और एक पहले ही लोड हो गया है, तो आप पहले से लोड की गई असेंबली में टाइप नहीं होने पर भी उम्मीद नहीं करेंगे।

ऐतिहासिक प्रयोजनों के लिए लेख के लिए लिंक: Resolving Assembly Loads

+0

जैसा कि आप मेरे पुराने प्रश्न http://stackoverflow.com/q/9158353/1061499 में भी पढ़ सकते हैं, मैं ऐसे एप्लिकेशन पर काम कर रहा हूं जो रन-टाइम पर इंटरफ़ेस के विभिन्न एप्लिकेशन लोड करने के लिए प्लग-इन दृष्टिकोण का उपयोग करता है।जब एप्लिकेशन बंद हो जाता है तो मुझे इन ऑब्जेक्ट्स को क्रमबद्ध करने की आवश्यकता होती है, फिर जब एप्लिकेशन को फिर से लॉन्च किया जाता है तो इन ऑब्जेक्ट्स को डी-सीरियलाइज़ किया जाना चाहिए। समस्या यह है कि ऑब्जेक्ट प्रकार रन-टाइम पर लोड होते हैं, इसलिए उनका प्रकार हल नहीं होता है ... – davioooh

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