2011-12-19 12 views
7

मेरे पास एक आवेदन a.exe है जो ठीक चल रहा है और एक असेंबली b.dll लोड कर चुका है, जो कि मायने रखता है तो प्रिज्म मॉड्यूल है। यह डीएलएल उस निर्देशिका से लोड है जो पथ में नहीं है लेकिन निर्देशिका में है जहां a.exe रहता है।सी # सिस्टम का deserialization। टाइप लोडेड असेंबली से एक प्रकार के लिए फेंकता

विधानसभा के लोड हो रहा है प्रिज्म द्वारा किया जाता है, और इस तरह की स्थापना की है:

public class MyModuleCatalog : ComposablePartCatalog 
{ 
    private readonly AggregateCatalog _catalog; 

    public MyModuleCatalog() 
    { 
     //directory Modules is not in the path, but all 
     //dependencies of b.dll are, so b.dll gets loaded fine 
    var asmCat = new AssemblyCatalog("Modules/b.dll"); 
    _catalog.Catalogs.Add(asmCat); 
    } 

    public override IQueryable<ComposablePartDefinition> Parts 
    { 
    get { return _catalog.Parts; } 
    } 
} 

class BootStrapper : MefBootstrapper 
{ 
    .... 
    protected override void ConfigureAggregateCatalog() 
    { 
    base.ConfigureAggregateCatalog(); 

    AggregateCatalog.Catalogs.Add(new AssemblyCatalog(Assembly.GetExecutingAssembly())); 
    AggregateCatalog.Catalogs.Add(new MyModuleCatalog()); 
    } 
    .... 
} 

b.dll में एक वर्ग ImInB है:

[Export] 
public class ImInB 
{ 
    public void DoIt() 
    { 
    try 
    { 
     var stream = new MemoryStream(); 
     //using System.Runtime.Serialization.Formatters. 
     var formatter = new BinaryBinaryFormatter(); 

     //serialize our type 
     formatter.Serialize(stream, this.GetType()); 

     //get it back 
     stream.Position = 0; 
     var obj = formatter.Deserialize(stream); //this throws?? 
    } 
    catch(Exception e) 
    { 
    } 
    } 
} 

यह वह जगह है सिर्फ उदाहरण कोड, और है एक स्थायी ढांचे का हिस्सा जो डेटाबेस को सेटिंग्स लोड/सहेजता है। ऑब्जेक्ट का प्रकार हमेशा क्रमबद्ध होता है और डेटाबेस में एकी के रूप में कार्य करता है। Deserializing पर, प्रकार लोड हो जाता है कि वस्तु के खिलाफ एक डबल चेक के रूप में वापस प्राप्त किया जाता है। समारोह a.exe से बुलाया जाता है:

container.GetExportedValue<ImInB>().DoIt(); 

अपवाद प्रकार (whih सफलतापूर्वक दो पंक्तियों पहले धारावाहिक) deserializing पर फेंक दिया है:

"Could not load file or assembly 'b.dll, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' 
or one of its dependencies. The system cannot find the file specified." 

सवाल:

  • कैसे है यह भी संभव है? समारोह को डीएलएल के भीतर से बुलाया जाता है, फिर भी कहता है कि यह उस डीएलएल को नहीं ढूंढ सकता है।
  • मैं इसे कैसे ठीक करूं? मैं कैसे बताऊँ Deserializeहे, कि dll पहले से ही भरी हुई है, की तलाश में मत जाओ यह

अद्यतन मेरे दूसरे प्रश्न मूल रूप से फेलिक्स कश्मीर द्वारा उत्तर दिया जाता है; निम्नलिखित कोड समस्या ठीक हो जाती:

public static class AssemblyResolverFix 
{ 
    //Looks up the assembly in the set of currently loaded assemblies, 
    //and returns it if the name matches. Else returns null. 
    public static Assembly HandleAssemblyResolve(object sender, ResolveEventArgs args) 
    { 
    foreach(var ass in AppDomain.CurrentDomain.GetAssemblies()) 
     if(ass.FullName == args.Name) 
     return ass; 
    return null; 
    } 
} 

//in main 
AppDomain.CurrentDomain.AssemblyResolve += AssemblyResolverFix.HandleAssemblyResolve; 

यह भी साबित होता है कि विधानसभा प्रभावी रूप से यह सभी निर्भरता है सहित, भरी हुई है, तो पहला सवाल रहता है: यह मेरे लिए एक रहस्य है क्यों ढांचे से ही इस को समझ नहीं सकता । इसके अलावा मैं इसे दूसरे एप्लिकेशन में पुन: पेश नहीं कर सकता जो लगभग समान संरचना का उपयोग करता है।

+0

क्या दोनों फ़ाइलों के नाम रिक्त स्थान हैं .. शायद आप उन्हें अपने उपयोग के साथ मैच स्तर पर और परियोजना स्तर पर बदल सकते हैं .. संकलक यह जान लेगा कि इसका संदर्भ कैसे दिया जाए अन्यथा ऐसा लगता है कि आपको उन विधियों के लिए पूरी तरह से योग्य नामस्थानों का उपयोग करने की आवश्यकता हो सकती है, जिन्हें लगता है या नहीं। – MethodMan

+0

क्या यह डीडीएल कुछ अन्य असेंबली पर भी निर्भर करता है? प्रतिबिंब के माध्यम से लोड करते समय सभी असेंबली स्थिर संदर्भ को संतुष्ट करने की आवश्यकता होती है। – Zenwalker

+0

@DJKRAZE आप किस फाइल का मतलब है? प्रश्न में सभी कोड एक एकल वर्ग में, एक एकल नामस्थान में है। हालांकि पाठ्यक्रम ए.एक्सई के पास अलग-अलग नामस्थान हैं, फिर b.dll – stijn

उत्तर

5

मुझे नहीं पता कि यह तब क्यों होता है जब डीएल पहले ही लोड हो जाता है लेकिन मुझे लगता है कि इसका क्रमशः सीरियलाइजेशन के साथ कुछ लेना देना नहीं है, यह मुझे .NET त्रुटि की तरह दिखता है।

यह वाला आपकी मदद कर सकता है, या सही दिशा में बताते हैं:

AppDomain current = AppDomain.CurrentDomain; 
current.AssemblyResolve += new ResolveEventHandler(HandleAssemblyResolve); 

static Assembly HandleAssemblyResolve(object sender, ResolveEventArgs args) 
{ 
    /* Load the assembly specified in 'args' here and return it, 
     if the assembly is already loaded you can return it here */ 
} 

हर जब एक dll याद आ रही है संकल्प विधि कहा जाता है, तो यह भी होना चाहिए जब अपने dll याद आ रही है। dotNET इसे नहीं ढूंढ सकता क्योंकि यह "मॉड्यूल" फ़ोल्डर में है, इसलिए आपको संदर्भ स्वयं को हल करना होगा।

+0

+1 यह वास्तव में इसे हल करता है। हैंडलएस्प्लिब्स के अंदर मैं लोडेड असेंबली पर बस लूप करता हूं और विधानसभा में लौटाता हूं। फुलनाम मैच ResolveEventArgs.Name से मेल खाता है। चूंकि यह आसान है, मुझे आश्चर्य है कि ढांचा खुद ही क्यों नहीं कर सकता है। – stijn

+0

@stijn निश्चित रूप से एक अच्छा सवाल है। आपको एक बग रिपोर्ट भरनी चाहिए, शायद आपको जवाब मिल जाए। –

+0

x0n के उत्तर पर मेरी टिप्पणी देखें: यह वास्तव में एक बग नहीं है, हालांकि यह निश्चित रूप से – stijn

1

टाइप पहचान एक चंचल चीज है।अनोखी सुजान कुक से इन दो ब्लॉग पोस्ट वास्तव में कुछ साल पहले मेरे लिए इसे मंजूरी दे दी:

LoadFile LoadFrom बनाम: http://blogs.msdn.com/b/suzcook/archive/2003/09/19/loadfile-vs-loadfrom.aspx एक बाध्यकारी प्रसंग का चयन: http://blogs.msdn.com/b/suzcook/archive/2003/05/29/57143.aspx

+1

+ बाउंटी परेशान कर रहा है, इससे मुझे यह पता लगाने में मदद मिली कि ऐसा क्यों होता है, प्रतिबिंबक की मदद से। एक प्रकार के deserialization के दौरान, सादा लोड कहा जाता है, लेकिन संभवतः उसी संदर्भ में नहीं जहां विधानसभा सूची में असेंबली लोड किया गया था (जो सादे लोड का भी उपयोग करता है)। लोड के नुकसान के तहत उल्लेख किया गया है 'अन्य संदर्भों में निर्भरता तब तक उपलब्ध नहीं है जब तक कि आप ऐपडोमेन की सदस्यता नहीं लेते हैं। एस्प्लोरर रिसेल्व इवेंट' – stijn

+0

@ स्टिजन धन्यवाद के लिए धन्यवाद, मैं सुजैन को आधा दे दूंगा लेकिन मुझे नहीं लगता कि वह काम करती है सीएलआर टीम अब :) – x0n