XmlSerializer निर्माता पर FileNotFoundException दे रहा है


347

जब मैं प्रकारों को क्रमबद्ध करने का प्रयास करता हूं, तो मैं जिस एप्लिकेशन के साथ काम कर रहा हूं वह विफल हो रहा है।

जैसा कथन

XmlSerializer lizer = new XmlSerializer(typeof(MyType));

पैदा करता है:

System.IO.FileNotFoundException occurred
  Message="Could not load file or assembly '[Containing Assembly of MyType].XmlSerializers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified."
  Source="mscorlib"
  FileName="[Containing Assembly of MyType].XmlSerializers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
  FusionLog=""
  StackTrace:
       at System.Reflection.Assembly._nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, Assembly locationHint, StackCrawlMark& stackMark, Boolean throwOnFileNotFound, Boolean forIntrospection)
       at System.Reflection.Assembly.nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, Assembly locationHint, StackCrawlMark& stackMark, Boolean throwOnFileNotFound, Boolean forIntrospection)

मैं अपनी कक्षा के लिए किसी विशेष धारावाहिक को परिभाषित नहीं करता।

मैं इस समस्या को कैसे ठीक करुं?


5
ठीक है, इसलिए यह सवाल मेरे पहले से पूछे गए VB प्रश्न का सिर्फ मेरा # # संस्करण है: stackoverflow.com/questions/294659/… धन्यवाद दोस्तों।
इरविन

1
छह साल में, @VladV का उत्तर सबसे सरल और सबसे कम प्रतिकूल प्रभाव वाला समाधान है। बस Generate serialization assembly"ऑटो" के बजाय ड्रॉप-डाउन को "ऑन" में बदलें ।
हेलिक

@ बाल: मैं असहमत हूँ। यह हमेशा काम नहीं करता है। कृपया व्लादि के जवाब में बेनोइट ब्लैंचोन की टिप्पणी देखें। मेरे लिए सबसे सरल उत्तर स्ट्रिंग फ़ाइलों में String.Collection का उपयोग नहीं करना है। इसके बजाय मैं उपयोग करता हूं: स्ट्रिंग [] आइटम = Settings.Default.StringofNewlineDelimitedItems.Split (नया [] {पर्यावरण.न्यूलाइन});
एंड्रयू डेनिसन

जवाबों:


388

मानो या न मानो, यह सामान्य व्यवहार है। एक अपवाद को फेंक दिया जाता है लेकिन XmlSerializer द्वारा नियंत्रित किया जाता है, इसलिए यदि आप इसे अनदेखा करते हैं तो सब कुछ ठीक होना चाहिए।

मैंने इसे बहुत कष्टप्रद पाया है, और यदि आप थोड़ा बहुत खोज करते हैं, तो इस बारे में कई शिकायतें आई हैं, लेकिन मैंने जो पढ़ा है, उसके बारे में कुछ भी करने पर Microsoft की योजना नहीं है।

आप डिबगिंग के दौरान हर समय अपवाद पॉपअप प्राप्त करने से बच सकते हैं यदि आप उस विशिष्ट अपवाद के लिए पहले मौका अपवादों को बंद कर देते हैं। दृश्य स्टूडियो में, करने के लिए जाना डीबग -> अपवाद (या प्रेस Ctrl+ Alt+ E), साझा भाषा क्रम अपवाद -> System.IO -> System.IO.FileNotFoundException

आप ब्लॉग पोस्ट C # XmlSerializer FileNotFound अपवाद (जिसमें क्रिस सेल्स टूल XmlSerializerPreCompiler की चर्चा करता है ) में इसके बारे में एक और तरीके के बारे में जानकारी पा सकते हैं ।


162
इस समस्या से छुटकारा पाने के संभावित तरीकों में से एक है टूल में "जस्ट माई कोड" विकल्प -> विकल्प -> डिबगिंग -> सामान्य विकल्प।
फ्रेडरिक

26
@ फ़्रेडरिक: यह टिप्पणी कमाल की है! मैं यहाँ "डब्ल्यूटीएफ!" के साथ बैठा हूँ! मेरे चेहरे पर अभिव्यक्ति, इस सहज अपवाद का शिकार करने की कोशिश कर रही है, और मुझे यह सवाल लगता है, जवाब के साथ (यह माइक्रोसॉफ्ट की गलती है, और क्या नया है?), लेकिन मैं अपवाद हैंडलिंग को अक्षम नहीं करना चाहता था, क्योंकि मुझे इसकी आवश्यकता हो सकती है मेरा कोड। A +!
कुंभा

27
मुझे लगता है कि नीचे हंस का सुझाव अधिक मूल्यवान है - एक अलग विधि कॉल का उपयोग करें जो इस अपवाद को बिल्कुल पैदा नहीं करता है: XmlSerializer serializer = XmlSerializer.FromTypes (नया [] {टाइपोफ़ (MyType)} [0];
उज्ज्वल

3
समस्या यह है कि यह मेरे परीक्षण में विफल रहता है, इसलिए मैं केवल अपवाद को "अनदेखा" नहीं कर सकता
Csaba Toth

16
मुझे खेद है, लेकिन यह एक भयानक सुझाव है। FileNotFoundException मेरे अनुभव में और अधिक सामान्य लोगों में से एक है, और इस अपवाद की रिपोर्टिंग को अक्षम करना भविष्य में किसी दिन बस परेशानी पूछ रहा है। 'जस्ट माई कोड' को चालू करने या नीचे वर्णित क्रमबद्ध विधानसभाओं के निर्माण को बेहतर बनाने के लिए बेहतर है।
क्वार्कली

104

जैसे मार्टिन शेरबर्न ने कहा, यह सामान्य व्यवहार है। XmlSerializer का निर्माणकर्ता पहले [YourAssembly] .XmlSerializers.dll नामक एक असेंबली खोजने की कोशिश करता है, जिसमें आपके प्रकार के क्रमांकन के लिए उत्पन्न वर्ग होना चाहिए। चूंकि ऐसा DLL अभी तक उत्पन्न नहीं हुआ है (वे डिफ़ॉल्ट रूप से नहीं हैं), एक FileNotFoundException को फेंक दिया गया है। जब ऐसा होता है, तो XmlSerializer का निर्माता उस अपवाद को पकड़ लेता है, और XmlSerializer के निर्माता द्वारा DLL स्वचालित रूप से रनटाइम पर उत्पन्न होता है (यह आपके कंप्यूटर के% अस्थायी% निर्देशिका में C # स्रोत फ़ाइलों को उत्पन्न करके किया जाता है, फिर C # संकलक का उपयोग करके उन्हें संकलित करता है)। एक ही प्रकार के लिए एक XmlSerializer के अतिरिक्त निर्माण केवल पहले से ही उत्पन्न DLL का उपयोग करेंगे।

अद्यतन: .NET 4.5 से शुरू होकर, XmlSerializerअब न तो कोड जनरेशन करता है और न ही C # कंपाइलर के साथ रनटाइम के दौरान एक सीरमाइज़र असेंबली बनाने के लिए कंपीटीशन करता है, जब तक कि किसी कॉन्फ़िगरेशन फ़ाइल सेटिंग को सेट करने के लिए स्पष्ट रूप से मजबूर न किया गया हो ( useLegacySlializerGeneration )। यह परिवर्तन निर्भरता को दूर करता है csc.exeऔर स्टार्टअप के प्रदर्शन में सुधार करता है। स्रोत: .NET फ्रेमवर्क 4.5 रीडमी , खंड 1.3.8.1।

अपवाद XmlSerializer के निर्माता द्वारा नियंत्रित किया जाता है। अपने आप को कुछ भी करने की आवश्यकता नहीं है, आप अपने कार्यक्रम को जारी रखने के लिए 'जारी रखें' (F5) पर क्लिक कर सकते हैं और सबकुछ ठीक हो जाएगा। यदि आप अपने प्रोग्राम के निष्पादन को रोकने वाले अपवादों से परेशान हैं और एक अपवाद सहायक को पॉप अप कर रहे हैं, तो आपके पास 'जस्ट माई कोड' बंद हो जाएगा, या आपके पास फाइलनोटफ़ाउंड एक्ससेप्शन सेट होगा जब फेंकने के दौरान निष्पादन को तोड़ने के लिए सेट किया जाएगा, जब इसके बजाय उपयोगकर्ता - बिना क्रिया '।

'जस्ट माई कोड' को एनेबल करने के लिए टूल्स >> विकल्प >> डिबगिंग >> जनरल >> इनेबल जस्ट माई कोड पर जाएं। जब FileNotFound को फेंक दिया जाता है, तो निष्पादन के ब्रेक को बंद करने के लिए, Debug >> Exception >> Find >> >> पर जाएं 'FileNotFoundException' >> एंटर करें। System.IO.FileNotFoundException से 'Thrown' चेकबॉक्स को अनचेक करें।


अद्यतन के लिए +1: यह विभिन्न मामलों की व्याख्या करता है जब परीक्षण मामलों को डीबग करना
mbx

3
आपका अपडेट बताता है कि यह अपवाद .NET 4.5 में नहीं होना चाहिए, लेकिन मैं अभी भी इसे देख रहा हूं।
टिम्बो

@ टिम्बो: मैं यह नहीं देखता कि आपको .NET 4.5 के साथ वह अपवाद क्यों नहीं मिलेगा। यह अभी भी एक फ़ाइल की तलाश में है, और यदि फ़ाइल गायब है, तो एक FileNotFoundExceptionफेंक दी जाएगी। अंतर यह नहीं है कि विधानसभा के अस्तित्व की जांच कैसे की जाती है, बल्कि यह निर्धारित करने के लिए कि यह गायब होने पर इसे कैसे उत्पन्न किया जाए। इससे पहले, यह IL को बनाने के लिए C # कंपाइलर को कॉल के साथ टेक्स्ट C # कोड जेनरेशन का उपयोग करता था। .NET 4.5 से शुरू होकर यह सीधे कंपाइलर के उपयोग के बिना IL का उत्सर्जन करता है।
एलोन गुरिलनेक

1
मेरी इच्छा है कि MS इसे लागू करेगा जैसे कि (File.Exists (...)) {Load} और {Fallback} के बजाय {Load} कैच {Fallback} की कोशिश करें। अपवाद आधारित प्रवाह नियंत्रण से बदबू आती है और मेरी डिबगिंग का अनुभव आवश्यकता से अधिक कठिन और भंगुर हो जाता है।
टिम्बो

1
@ टिम्बो: एक साधारण File.Exists()पर्याप्त नहीं हो सकता है। असेंबली का पता लगाना एक सरल मामला नहीं है, रनटाइम कई स्थानों पर दिखता है और मेरा मानना ​​है कि वातावरण के अनुसार व्यवहार में बदलाव (आईआईएस, आदि में होस्ट किए जा रहे कंसोल एप्लिकेशन)। मुझे लगता है कि जो लागू किया जाना चाहिए था वह एक TryLoadAssembly()या कुछ इसी तरह का था।
एलन गुरलनक

63

विजुअल स्टूडियो प्रोजेक्ट प्रॉपर्टीज ("बिल्ड" पेज में, अगर मैं इसे सही तरीके से याद करता हूं) "सीरियलाइजेशन असेंबली जेनरेट करने" का एक विकल्प है। एक परियोजना के लिए इसे चालू करने का प्रयास करें जो [MyType की युक्त विधानसभा] उत्पन्न करता है ।


4
यह भी देखें कि यदि सीरियल असेंबली अभी भी Visual Studio द्वारा नहीं बनाई गई है, तो stackoverflow.com/a/8798289/1164966 देखें ।
बेनोइट ब्लांचन

सबसे अच्छा, स्पष्ट, संक्षिप्त जवाब! काश मैं भी फिर से मतदान कर पाता!
जॉन ज़ब्रोस्की 22

59

उसके लिए वर्कअराउंड है। यदि तुम प्रयोग करते हो

XmlSerializer lizer = XmlSerializer.FromTypes(new[] { typeof(MyType) })[0];

यह उस अपवाद से बचना चाहिए। इसने मेरे लिए काम किया।

चेतावनी: कई बार उपयोग न करें, या आपके पास स्मृति रिसाव होगा

यदि आप XmlSerializerएक से अधिक बार एक ही प्रकार के उदाहरण बनाने के लिए इस विधि का उपयोग करते हैं, तो आप पागलों की तरह स्मृति को लीक कर देंगे !

ऐसा इसलिए है क्योंकि यह विधि अंतर्निहित कैशिंग को बायपास करती है बशर्ते कि XmlSerializer(type)और XmlSerializer(type, defaultNameSpace)कंस्ट्रक्टर (अन्य सभी कंस्ट्रक्टर भी कैश को बायपास करें)।

यदि आप XmlSerializer बनाने के लिए किसी भी विधि का उपयोग करते हैं जो इन दो कंस्ट्रक्टरों के माध्यम से नहीं है, तो आपको अपनी कैशिंग को लागू करना होगा या आपको मेमोरी का रक्तस्राव होगा।


44
चेतावनी: यदि आप XmlSerializerएक से अधिक बार एक ही प्रकार के उदाहरण बनाने के लिए इस पद्धति का उपयोग करते हैं, तो आप पागलों की तरह स्मृति को लीक कर देंगे ! ऐसा इसलिए है क्योंकि यह विधि अंतर्निहित कैशिंग को बायपास करती है बशर्ते कि XmlSerializer(type)और XmlSerializer(type, defaultNameSpace)कंस्ट्रक्टर (अन्य सभी कंस्ट्रक्टर भी कैश को बायपास करें)। यदि आप XmlSerializerइन दो कंस्ट्रक्टर्स के माध्यम से बनाने के लिए किसी भी विधि का उपयोग नहीं करते हैं, तो आपको अपनी खुद की कैशिंग को लागू करना होगा या आपको मेमोरी को रक्तस्राव करना होगा।
एलोन गुरिलनेक

4
@AllonGuralnek खैर मैं शापित हो जाऊंगा ... आप बिल्कुल सही हैं; रिफ्लेक्टर के माध्यम से और खुदाई करने से पता चलता है कि जब यह कैश की जाँच करता है, तो यह क्रमिक असेंबली बनाने के बाद ऐसा करता है ! WTF?!?
जेरकीबॉल

4
एक ज्ञात बग को चालू करता है: weblogs.asp.net/cschittko/archive/2005/01/14/353435.aspx
JerKimball

3
@JerKimball: वह पृष्ठ वास्तव में झूठ नहीं है। जैसा कि आपने खोजा था, FromTypesकैश को आबाद करने के लिए प्रकट होता है। तो यह XmlSerializerएक बयान में एक खाली कैश को गर्म करने का एक वैध तरीका होना चाहिए (जैसे कि लेख बताता है), लेकिन इससे कुछ भी प्राप्त करने का एक बहुत बुरा तरीका (केवल सबसे सरल कंस्ट्रक्टर के माध्यम से किया जाना चाहिए)। किसी भी मामले में, मुझे नहीं पता था कि यह एक बग था, मैं हमेशा कुछ भी सोचता था कि लीक को लीक करना चाहिए (जैसे कि अधिक उन्नत XmlSerializerनिर्माणकर्ता)। मैं भी FromTypes()आप का उपयोग कर सकते हैं पर विचार नहीं किया है types.Select(t => new XmlSerializer(t))
एलोन गुरलीनक

2
@AllonGuralnek उपयोग करने के गैर-संभावना वाले पहलू में FromTypesइसकी अपील है - यहां तक ​​कि फेंक दिए गए अपवाद सभी पकड़े जाते हैं, यह एक अमूल्य संचालन है; 'कैशे योर वे योर अप्रोच' एकमात्र वर्कअराउंड प्रतीत होता है, क्योंकि एकमात्र आधिकारिक रूप से समर्थित फिक्स एक अस्पष्ट वेब-आधारित असेंबली में दिखता है। (संपादित करें: स्पष्ट रूप से, मैं डेटा कॉन्ट्रैक्ट पर सब कुछ पोर्ट करने के लिए हूं :))
जेरकीबॉल

22

मैं इस सटीक मुद्दे पर भाग गया और वर्णित समाधानों में से किसी के द्वारा इसे प्राप्त नहीं कर सका।

फिर मैंने आखिरकार एक उपाय ढूंढ निकाला। ऐसा प्रतीत होता है कि धारावाहिक को न केवल प्रकार की आवश्यकता है, बल्कि नेस्टेड प्रकार भी हैं। इसे बदलना:

XmlSerializer xmlSerializer = new XmlSerializer(typeof(T));

इसके लिए:

XmlSerializer xmlSerializer = new XmlSerializer(typeof(T).GetNestedTypes());

मेरे लिए मुद्दा तय किया। और कोई अपवाद या कुछ भी नहीं।


8
इसने मेरे लिए काम किया। .Net4.0 का उपयोग करना प्रारूप हैvar xmlSerializer = new XmlSerializer(typeof(T), typeof(T).GetNestedTypes());
user3161729

1
यह मेरे लिए भी काम किया। लेकिन यह केवल क्रमबद्ध होने पर आवश्यक प्रतीत होता है, न कि डिसेर्बलाइज करते समय। शायद यह समझ में आता है, शायद यह नहीं है।
स्टीविन्क सिप

2
यह स्मृति रिसाव भी पैदा करता है, यदि बहुत बार चलाया जाए।
वलोडिमिर कोटिलो

9

मेरा समाधान सीधे धारावाहिक बनाने के लिए प्रतिबिंब पर जाना है। यह अपवाद का कारण बनने वाली अजीब फ़ाइल लोडिंग को बायपास करता है। मैंने इसे एक हेल्पर फंक्शन में पैक किया, जो कि धारावाहिक को कैशिंग करने का भी ध्यान रखता है।

private static readonly Dictionary<Type,XmlSerializer> _xmlSerializerCache = new Dictionary<Type, XmlSerializer>();

public static XmlSerializer CreateDefaultXmlSerializer(Type type) 
{
    XmlSerializer serializer;
    if (_xmlSerializerCache.TryGetValue(type, out serializer))
    {
        return serializer;
    }
    else
    {
        var importer = new XmlReflectionImporter();
        var mapping = importer.ImportTypeMapping(type, null, null);
        serializer = new XmlSerializer(mapping);
        return _xmlSerializerCache[type] = serializer;
    }
}

यहां 2 समस्याएं - पहला आपका कोड थ्रेड-सुरक्षित नहीं है, और दूसरा (अधिक महत्वपूर्ण बात) आप यह दोहराने का प्रयास कर रहे हैं कि .net रनटाइम पहले से ही करता है (आपके द्वारा उपयोग किए जा रहे ctor के आधार पर)। अर्थात इस कोड की कोई आवश्यकता नहीं है
डेव ब्लैक

@DaveBlack: हाँ, एक ConcurrentDictionary लिए कैशिंग के साथ quadfinity का जवाब बेहतर होगा
डी - बी

@db मेरा दूसरा बिंदु यह था कि कैशिंग की आवश्यकता भी नहीं है - जब तक आप 2 में से एक का उपयोग कर रहे हैं कि फ्रेमवर्क कैश (ओपी पहले का उपयोग कर रहा है)। MSDN से: प्रदर्शन बढ़ाने के लिए, XML क्रमांकन बुनियादी ढांचा गतिशील रूप से असेंबली उत्पन्न करता है और निर्दिष्ट प्रकारों को डीरियलाइज़ करता है। फ्रेमवर्क उन विधानसभाओं को ढूंढता और पुन: उपयोग करता है। यह व्यवहार केवल तब होता है जब निम्न कॉस्टर का उपयोग किया जाता है: XmlSerializer.XmlSerializer (प्रकार) XmlSerializer.XmlSerializer (प्रकार, स्ट्रिंग) संदर्भ: msdn.microsoft.com/en-us/library/…
डेव ब्लैक

@DaveBlack: हां, लेकिन ये कंस्ट्रक्टर आंतरिक रूप से तब भी अपवाद फेंकते और पकड़ते हैं, जब उपयोग पूरी तरह से वैध हो। यह बुरा है, और यही कारण है कि ओपी ने पहली जगह में सवाल पूछा।
d - b

@db ट्रू, लेकिन मेरे कहने का मतलब (लेकिन स्पष्ट नहीं था - मेरी माफ़ी) यह था कि आपके सोल की केवल वही पंक्तियाँ आवश्यक हैं जो अन्य स्थिति में पहली 3 पंक्तियाँ हैं।
डेव ब्लैक

8

अपवाद से बचने के लिए आपको दो काम करने होंगे:

  1. क्रमबद्ध वर्ग में एक विशेषता जोड़ें (मुझे आशा है कि आपके पास पहुंच है)
  2. Sgen.exe के साथ क्रमांकन फ़ाइल जनरेट करें

अपनी कक्षा में System.Xml.Serialization.XmlSerializerAssembly विशेषता जोड़ें। 'MyAssembly' को विधानसभा के नाम से बदलें जहां MyClass है।

[Serializable]
[XmlSerializerAssembly("MyAssembly.XmlSerializers")]
public class MyClass
{

}

Sgen.exe उपयोगिता का उपयोग करके क्रमांकन फ़ाइल बनाएं और इसे क्लास की असेंबली के साथ तैनात करें।

'sgen.exe MyAssembly.dll' फ़ाइल MyAssembly.XmlSerializers.dll फ़ाइल जनरेट करेगा

इन दो परिवर्तनों के कारण .net सीधे असेंबली खोजने के लिए होगा। मैंने इसे चेक किया और यह Visual Studio 2008 के साथ .NET फ्रेमवर्क 3.5 पर काम करता है


ठीक है, और क्या यह इन परिवर्तनों के बिना विफल हो गया, और यदि हां, तो क्यों?
जॉन सॉन्डर्स 1

1
मुझे कोई कारण नहीं मिल सकता है कि मेरी परियोजना, वीएस2012 में 4.0, अचानक विफल क्यों हो गई। "अनदेखा करना" त्रुटि एक विकल्प नहीं था, क्योंकि यह हर बार हुआ जब मैंने सक्रिय निर्देशिका तक पहुंचने की कोशिश की; इस प्रकार अनदेखी का अर्थ प्रामाणिक नहीं होगा। मैं अभी भी बहुत निराश हूं कि VS2012 क्रमबद्ध DLL को ठीक से ऑटो-जेनरेट नहीं करेगा। हालाँकि, इन चरणों ने सही समाधान प्रदान किया।
सूफूका

6

इस अपवाद को एक प्रबंधित डिबगिंग सहायक (MDA) द्वारा भी रोका जा सकता है जिसे BindingFailure कहा जाता है।

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

यह वास्तव में इस परिदृश्य को छोड़कर उपयोगी नहीं है, क्योंकि जैसा कि अन्य पोस्टरों ने कहा है, जब एक बाध्यकारी त्रुटि Serializer के कंस्ट्रक्टर द्वारा फंस जाती है, क्रमबद्ध असेंबली को रनटाइम पर फिर से बनाया जाता है। तो आप आमतौर पर इसे बंद कर सकते हैं।


6

फ़ंक्शन XmlSerializer.FromTypes अपवाद को नहीं फेंकता है, लेकिन यह मेमोरी को लीक करता है। यही कारण है कि आपको इस तरह के धारावाहिक को हर प्रकार के लिए कैश करने की आवश्यकता है ताकि बनाए गए प्रत्येक उदाहरण के लिए मेमोरी लीक न हो।

अपनी खुद की XmlSerializer फैक्ट्री बनाएं और इसे बस उपयोग करें:

XmlSerializer serializer = XmlSerializerFactoryNoThrow.Create(typeof(MyType));

कारखाने लग रहा है पसंद:

public static class XmlSerializerFactoryNoThrow
{
    public static Dictionary<Type, XmlSerializer> _cache = new Dictionary<Type, XmlSerializer>();

    private static object SyncRootCache = new object();        

    /// <summary>
    /// //the constructor XmlSerializer.FromTypes does not throw exception, but it is said that it causes memory leaks
    /// http://stackoverflow.com/questions/1127431/xmlserializer-giving-filenotfoundexception-at-constructor
    /// That is why I use dictionary to cache the serializers my self.
    /// </summary>
    public static XmlSerializer Create(Type type)
    {
        XmlSerializer serializer;

        lock (SyncRootCache)
        {
            if (_cache.TryGetValue(type, out serializer))
                return serializer;
        }

        lock (type) //multiple variable of type of one type is same instance
        {
            //constructor XmlSerializer.FromTypes does not throw the first chance exception           
            serializer = XmlSerializer.FromTypes(new[] { type })[0];
            //serializer = XmlSerializerFactoryNoThrow.Create(type);
        }

        lock (SyncRootCache)
        {
            _cache[type] = serializer;
        }
        return serializer;
    }       
}

मेमोरी लीक की संभावना के बिना अधिक जटिल संस्करण (कृपया कोई व्यक्ति कोड की समीक्षा करें):

    public static XmlSerializer Create(Type type)
    {
        XmlSerializer serializer;

        lock (SyncRootCache)
        {
            if (_cache.TryGetValue(type, out serializer))
                return serializer;
        }

        lock (type) //multiple variable of type of one type is same instance
        {
            lock (SyncRootCache)
            {
                if (_cache.TryGetValue(type, out serializer))
                    return serializer;
            }
            serializer = XmlSerializer.FromTypes(new[] { type })[0];
            lock (SyncRootCache)
            {
                _cache[type] = serializer;
            }
        }          
        return serializer;
    }       
}

आपको इसके स्थान पर समवर्ती छाया का उपयोग करना चाहिए। यह कोड गतिरोध कर सकता है।
बेहरोज़

अगर लॉक के साथ सभी प्रबंधन लॉक सेक्शन में हैं तो यह गतिरोध कैसे हो सकता है?
टॉमस क्यूब्स

क्षमा करें, मुझे शब्द भ्रमित हो गए। मेरा मतलब है कि यह एक से अधिक बार आइटम सम्मिलित कर सकता है। क्योंकि जब यह अस्तित्व की जाँच करता है और जब यह सम्मिलित करता है, तो इसके बीच एक अंतर होता है। समवर्ती शब्दकोश कुछ प्रकार के दो-चरण लॉकिंग (बैग [0] और फिर बैग [हैश]]) का उपयोग करता है और उस बैग का संदर्भ रखता है जिसमें आपके द्वारा काम किए जा रहे आइटम सम्मिलित / शामिल होने चाहिए। यह तेज, सुरक्षित और साफ है।
बेहरोज़ 12

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

मैं कल्पना कर सकता हूं कि समाधान और भी बेहतर हो सकता है (सैद्धांतिक स्मृति रिसाव के बिना), लेकिन अधिक जटिल।
टॉमस क्यूब्स

3

दूसरी ओर संकलन त्रुटियों का निवारण बहुत जटिल है। ये समस्याएं संदेश के साथ खुद को FileNotFoundException में प्रकट करती हैं:

File or assembly name abcdef.dll, or one of its dependencies, was not found. File name: "abcdef.dll"
   at System.Reflection.Assembly.nLoad( ... )
   at System.Reflection.Assembly.InternalLoad( ... )
   at System.Reflection.Assembly.Load(...)
   at System.CodeDom.Compiler.CompilerResults.get_CompiledAssembly() 

आप आश्चर्यचकित हो सकते हैं कि एक फ़ाइल जो अपवाद नहीं मिली है, उसे एक सीरियलाइज़र ऑब्जेक्ट को त्वरित करने के साथ क्या करना है, लेकिन याद रखें: कंस्ट्रक्टर सी # फाइलें लिखता है और उन्हें संकलित करने की कोशिश करता है। इस अपवाद का कॉल स्टैक उस संदेह का समर्थन करने के लिए कुछ अच्छी जानकारी प्रदान करता है। अपवाद तब हुआ जब XmlSerializer ने SystemReflection.Assembly.Load पद्धति को कॉल करके कोडडॉम द्वारा उत्पन्न एक असेंबली को लोड करने का प्रयास किया। अपवाद यह स्पष्टीकरण नहीं प्रदान करता है कि XmlSerializer को बनाने वाला असेंबली मौजूद क्यों नहीं था। सामान्य तौर पर, असेंबली मौजूद नहीं है क्योंकि संकलन विफल हो गया, जो हो सकता है क्योंकि, दुर्लभ परिस्थितियों में, क्रमांकन विशेषताएँ कोड उत्पन्न करती हैं जो C # संकलक संकलन करने में विफल रहता है।

नोट यह त्रुटि तब भी होती है जब XmlSerializer एक खाते या एक सुरक्षा वातावरण के तहत चलता है जो अस्थायी निर्देशिका तक पहुंचने में सक्षम नहीं है।

स्रोत : http://msdn.microsoft.com/en-us/library/aa302290.aspx


उन्होंने यह निर्दिष्ट नहीं किया कि यह रनटाइम के लिए है। एक और बात जो मैं सोच सकता हूं, वह यह है कि आपके पास एक नाम स्थान / वर्ग संघर्ष है। आपके MyType का पूरा नाम क्या है?
ज़ैफ्राक्स

हाँ, मैंने उर लिंक की जाँच की, कंस्ट्रक्टर्स की जानकारी, हालांकि मददगार, वह नहीं थी जिसकी मुझे ज़रूरत थी।
इरविन

5
@SpaceghostAl आप रनटाइम पर संकलन कर सकते हैं। और यही XmlSerializer करता है। यह गतिशील रूप से रनटाइम असेंबली का निर्माण करता है जो (डी) एक्सएमएल को विशेष प्रकार के लिए अनुक्रमित करता है। जिस भी कारण से यह प्रक्रिया ओपी के लिए विफल हो जाती है। एक अस्थायी निर्देशिका पर उदाहरण के लिए अनुमति की समस्याओं के कारण। (डिस्क स्पेस के बाहर भी उतना ही मूर्खतापूर्ण हो सकता है।)
nos

क्या तुम इसके बारे में निश्चित हो? मुझे पूरा यकीन था कि सीरियलाइजेशन का सामान असेंबली में एक नाम YourAssemblyName.XmlSerializers.dll के साथ संकलित हो जाता है , निर्माण के दौरान , रनटाइम पर संकलित नहीं किया जाता है। यह सभी प्रकार के कारणों में विफल हो सकता है, तैनाती फ़ोल्डर में सभी NTFS अनुमतियों में से कम से कम।
टॉमफनिंग

1
काश मैं इसे कई बार बढ़ा पाता। खाते के बारे में आपके नोट ने अस्थायी फ़ोल्डर तक पहुँचने में सक्षम नहीं होने पर मेरे लिए उत्तर ट्रिगर किया। एक बार जब मैंने सर्वर पर व्यवस्थापक समूह में अपना सेवा खाता जोड़ा, तो यह बस काम कर गया। धन्यवाद!
बॉब हॉर्न

2

विजुअल स्टूडियो प्रोजेक्ट प्रॉपर्टीज में "सीरियलाइजेशन असेंबली जनरेट" करने का विकल्प है। एक परियोजना के लिए इसे चालू करने का प्रयास करें जो [MyType की युक्त विधानसभा] उत्पन्न करता है।


1

एक कस्टम वर्ग क्रमबद्ध करने के लिए:

[Serializable]
public class TestClass
{
    int x = 2;
    int y = 4;
    public TestClass(){}
    public TestClass(int x, int y)
    {
        this.x = x;
        this.y = y;
    }

    public int TestFunction()
    {
        return x + y;
    }
}

मैंने कोड स्निपेट संलग्न किया है। शायद यह आपकी मदद कर सकता है।

static void Main(string[] args)
{
    XmlSerializer xmlSerializer = new XmlSerializer(typeof(TestClass));

    MemoryStream memoryStream = new MemoryStream();
    XmlTextWriter xmlWriter = new XmlTextWriter(memoryStream, Encoding.UTF8);

    TestClass domain = new TestClass(10, 3);
    xmlSerializer.Serialize(xmlWriter, domain);
    memoryStream = (MemoryStream)xmlWriter.BaseStream;
    string xmlSerializedString = ConvertByteArray2Str(memoryStream.ToArray());

    TestClass xmlDomain = (TestClass)DeserializeObject(xmlSerializedString);

    Console.WriteLine(xmlDomain.TestFunction().ToString());
    Console.ReadLine();
}

2
-1 संसाधन लीक को रोकने के लिए, और XmlTextWriter का उपयोग करने के लिए ब्लॉकों का उपयोग नहीं करने के लिए।
जॉन सॉन्डर्स

ठीक है सहमत हूँ, लेकिन फिर भी मैंने XmlSerializer xmlSerializer = new XmlSerializer (टाइपोफ़ (TestClass)) का उपयोग किया है; लेकिन मुझे उक्त अपवाद नहीं मिल रहा है।
शाहजहां

1

मुझे एक समान समस्या हो रही थी, और अपवाद की अनदेखी करना मेरे लिए काम नहीं करता था। मेरा कोड NServiceBus के कॉन्फ़िगरेशन को कॉल कर रहा थाConfigure.With(...).XmlSerializer()...

मेरे लिए यह तय था कि मुझे अपने प्रोजेक्ट के लिए प्लेटफॉर्म बदलना है।

  1. बिल्ड \ कॉन्फ़िगरेशन प्रबंधक पर जाएं ...
  2. अपना प्रोजेक्ट ढूंढें और प्लेटफ़ॉर्म बदलें (मेरे मामले में x86 से किसी भी सीपीयू तक)

1

बस संदर्भ के रूप में। DB उत्तर और टिप्पणियों से लेते हुए, मैं इस समाधान के साथ आया जो DB समाधान के करीब है। यह मेरे सभी मामलों में ठीक काम करता है और यह थ्रेड सेफ है। मुझे नहीं लगता कि एक समवर्ती का उपयोग करना ठीक रहा होगा।

using System;
using System.Collections.Generic;
using System.Xml.Serialization;

namespace HQ.Util.General
{
    public class XmlSerializerHelper
    {
        private static readonly Dictionary<Type, XmlSerializer> _dictTypeToSerializer = new Dictionary<Type, XmlSerializer>();

        public static XmlSerializer GetSerializer(Type type)
        {
            lock (_dictTypeToSerializer)
            {
                XmlSerializer serializer;
                if (! _dictTypeToSerializer.TryGetValue(type, out serializer))
                {
                    var importer = new XmlReflectionImporter();
                    var mapping = importer.ImportTypeMapping(type, null, null);
                    serializer = new XmlSerializer(mapping);
                    return _dictTypeToSerializer[type] = serializer;
                }

                return serializer;
            }
        }
    }
}

उपयोग:

        if (File.Exists(Path))
        {
            using (XmlTextReader reader = new XmlTextReader(Path))
            {
                // XmlSerializer x  = new XmlSerializer(typeof(T));
                var x = XmlSerializerHelper.GetSerializer(typeof(T));

                try
                {
                    options = (OptionsBase<T>)x.Deserialize(reader);
                }
                catch (Exception ex)
                {
                    Log.Instance.AddEntry(LogType.LogException, "Unable to open Options file: " + Path, ex);
                }
            }
        }

0

आपका प्रकार अन्य विधानसभाओं को संदर्भित कर सकता है जो न तो जीएसी में और न ही आपके स्थानीय बिन फ़ोल्डर ==> में पाया जा सकता है ...

"या इसकी निर्भरता में से एक। सिस्टम निर्दिष्ट फ़ाइल नहीं ढूँढ सकता है"

क्या आप उस प्रकार का उदाहरण दे सकते हैं जिसे आप क्रमबद्ध करना चाहते हैं?

ध्यान दें: सुनिश्चित करें कि आपका प्रकार Serializable लागू करता है।


0

मुझे वही त्रुटि मिल रही थी, और यह उस प्रकार के कारण था जिस तरह मैं डिफाल्टर करने की कोशिश कर रहा था कि डिफ़ॉल्ट पैरामीटर रहित कंस्ट्रक्टर न हो । मैंने एक कंस्ट्रक्टर जोड़ा, और यह काम करने लगा।


0

मुझे वही समस्या थी जब तक कि मैंने एक्सएसडी से क्लास उत्पन्न करने के लिए एक 3 पार्टी टूल का उपयोग नहीं किया और यह काम किया! मुझे पता चला कि उपकरण मेरी कक्षा के शीर्ष पर कुछ अतिरिक्त कोड जोड़ रहा था। जब मैंने अपने मूल वर्ग के शीर्ष पर यही कोड जोड़ा तो यह काम कर गया। यहाँ मैंने क्या जोड़ा है ...

#pragma warning disable
namespace MyNamespace
{
  using System;
  using System.Diagnostics;
  using System.Xml.Serialization;
  using System.Collections;
  using System.Xml.Schema;
  using System.ComponentModel;
  using System.Xml;
  using System.Collections.Generic;

  [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "4.6.1064.2")]
  [System.SerializableAttribute()]
  [System.Diagnostics.DebuggerStepThroughAttribute()]
  [System.ComponentModel.DesignerCategoryAttribute("code")]
  [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
  [System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = false)]
  public partial class MyClassName
  {
  ...

0

एक का उपयोग करने के लिए कई सिफारिशें देखीं ConcurrentDictionary, लेकिन इसका कोई ठोस उदाहरण नहीं है, इसलिए मैं अपनी टोपी को इस समाधान की दौड़ में फेंकने जा रहा हूं। मैं थ्रेड-सुरक्षित डेवलपर नहीं हूं, इसलिए यदि यह कोड ठोस नहीं है, तो कृपया उन लोगों के लिए बोलें, जो बाद में आते हैं।

public static class XmlSerializerHelper
{
    private static readonly ConcurrentDictionary<Type, XmlSerializer> TypeSerializers = new ConcurrentDictionary<Type, XmlSerializer>();

    public static XmlSerializer GetSerializer(Type type)
    {
        return TypeSerializers.GetOrAdd(type,
        t =>
        {
            var importer = new XmlReflectionImporter();
            var mapping = importer.ImportTypeMapping(t, null, null);
            return new XmlSerializer(mapping);
        });
    }
}

मैंने अन्य पोस्टों को शामिल किया है ConcurrentDictionaryऔर Lazyमूल्य को लोड कर रहा है। मुझे यकीन नहीं है कि यहाँ प्रासंगिक है या नहीं, लेकिन यहाँ उस के लिए कोड है:

private static readonly ConcurrentDictionary<Type, Lazy<XmlSerializer>> TypeSerializers = new ConcurrentDictionary<Type, Lazy<XmlSerializer>>();

public static XmlSerializer GetSerializer(Type type)
{
    return TypeSerializers.GetOrAdd(type,
    t =>
    {
        var importer = new XmlReflectionImporter();
        var mapping = importer.ImportTypeMapping(t, null, null);
        var lazyResult = new Lazy<XmlSerializer>(() => new XmlSerializer(mapping), LazyThreadSafetyMode.ExecutionAndPublication);
        return lazyResult;
    }).Value;
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.