باستخدام .Net ما هي القيود (إن وجدت) الموجودة في استخدام XmlSerializer؟

StackOverflow https://stackoverflow.com/questions/109318

  •  01-07-2019
  •  | 
  •  

سؤال

باستخدام .Net ما هي القيود (إن وجدت) الموجودة في استخدام XmlSerializer؟على سبيل المثال، هل يمكنك إجراء تسلسل للصور إلى XML؟

هل كانت مفيدة؟

المحلول

يحتوي XmlSerializer على بعض العيوب.

  1. يجب أن يعرف جميع الأنواع التي يتم تسلسلها.لا يمكنك تمرير شيء عبر الواجهة يمثل نوعًا لا يعرفه المُسلسِل.
  2. لا يمكنه عمل مراجع دائرية.
  3. سيتم إجراء تسلسل للكائن نفسه عدة مرات إذا تمت الإشارة إليه عدة مرات في الرسم البياني للكائن.
  4. لا يمكن التعامل مع تسلسل الحقول الخاصة.

لقد كتبت (بغباء) برنامج التسلسل الخاص بي للتغلب على بعض هذه المشكلات.لا تفعل ذلك؛إنه عمل كثير، وستجد فيه أخطاء دقيقة خلال أشهر.الشيء الوحيد الذي اكتسبته في كتابة المُسلسِل والمنسق الخاص بي هو التقدير الأكبر للتفاصيل الدقيقة التي ينطوي عليها تسلسل الرسم البياني للكائنات.

لقد وجدت NetDataContractSerializer عندما خرج WCF.إنه يفعل كل الأشياء من الأعلى التي لا يفعلها XmlSerializer.إنه يقود عملية التسلسل بطريقة مشابهة لـ XmlSerializer.يقوم أحدهم بتزيين الخصائص أو الحقول المختلفة بسمات لإبلاغ المُسلسِل بما يجب إجراء تسلسل له.لقد استبدلت المُسلسل المخصص الذي كتبته باستخدام NetDataContractSerializer وكنت سعيدًا جدًا بالنتائج.سأكون في غاية يوصي به.

نصائح أخرى

أجد بشكل عام أن XmlSerializer هو خيار سيئ لأي POCO أكثر من مجرد DTO.إذا كنت بحاجة إلى XML محدد، فيمكنك الانتقال إلى مسار Xml*Attribute و/أو IXmlSerializable - ولكن يتبقى لك كائن مشوه تمامًا.

بالنسبة لبعض الأغراض، فإنه لا يزال خيارًا واضحًا - حتى مع القيود المفروضة عليه.ولكن، لمجرد تخزين البيانات وإعادة تحميلها، وجدت أن BinaryFormatter خيار أسهل بكثير مع مخاطر أقل.

فيما يلي قائمة ببعض مضايقات XmlSerializer - معظمها تعرضت للعض في وقت أو آخر، والبعض الآخر وجدته في MSDN:

  • يتطلب منشئًا عامًا وليس منشئ وسيطات
  • يقوم فقط بإجراء تسلسل لخصائص وحقول القراءة/الكتابة العامة
  • يتطلب معرفة جميع الأنواع
  • في الواقع يستدعي get_* وset_*، لذلك يتم التحقق من الصحة، وما إلى ذلك.سيتم تشغيله.قد يكون هذا جيدًا أو سيئًا (فكر في ترتيب المكالمات أيضًا)
  • سيتم فقط إجراء تسلسل لمجموعات IEnumerable أو ICollection المطابقة لقواعد محددة

يوفر XmlSerializer معاملة خاصة للفئات التي تطبق IEnumerable أو ICollection.يجب أن تقوم الفئة التي تطبق IEnumerable بتطبيق أسلوب Add عام يأخذ معلمة واحدة.يجب أن تكون معلمة أسلوب الإضافة من نفس النوع الذي تم إرجاعه من الخاصية الحالية على القيمة التي تم إرجاعها من GetEnumerator، أو أحد أسس هذا النوع.

يجب أن تحتوي الفئة التي تطبق ICollection (مثل CollectionBase) بالإضافة إلى IEnumerable على خاصية عامة مفهرسة للعنصر (مفهرس في C#) تأخذ عددًا صحيحًا، ويجب أن تحتوي على خاصية Count عامة من النوع عدد صحيح.يجب أن تكون معلمة أسلوب الإضافة من نفس النوع الذي تم إرجاعه من خاصية العنصر، أو أحد أسس هذا النوع.بالنسبة للفئات التي تطبق ICollection، يتم استرداد القيم المراد إجراء تسلسل لها من خاصية العنصر المفهرس، وليس عن طريق استدعاء GetEnumerator.

  • لا يقوم بإجراء تسلسل IDictionary
  • يستخدم التجميعات التي تم إنشاؤها ديناميكيًا، والتي قد لا يتم إلغاء تحميلها من مجال التطبيق.

لزيادة الأداء، تقوم البنية التحتية لتسلسل XML بشكل ديناميكي بإنشاء تجميعات لإجراء تسلسل وإلغاء تسلسل الأنواع المحددة.تبحث البنية التحتية عن تلك التجميعات وتعيد استخدامها.يحدث هذا السلوك فقط عند استخدام المنشئات التالية:

xmlserializer.xmlserializer (type) xmlserializer.xmlserializer (النوع ، سلسلة)

إذا كنت تستخدم أيًا من المنشئات الأخرى، فسيتم إنشاء إصدارات متعددة من نفس التجميع ولن يتم إلغاء تحميلها مطلقًا، مما يؤدي إلى تسرب الذاكرة وضعف الأداء.

  • لا يمكن إجراء تسلسل ArrayList[] أو List<T>[]
  • لديه حالات حافة غريبة أخرى

لا يمكن إنشاء مثيل XmlSerializer لإجراء تسلسل للتعداد إذا تحققت الشروط التالية:التعداد من النوع غير الموقع طويل (ulong في C#) ويحتوي التعداد على أي عضو بقيمة أكبر من 9,223,372,036,854,775,807.

لم تعد فئة XmlSerializer تقوم بإجراء تسلسل للكائنات التي تم وضع علامة عليها على أنها [قديمة].

يجب أن يكون لديك إذن بالكتابة إلى الدليل المؤقت (كما هو محدد بواسطة متغير البيئة TEMP) لإلغاء تسلسل كائن.

  • يتطلب قراءة .InnerException للحصول على أي معلومات مفيدة عن الأخطاء

هناك مشكلة أخرى وهي أن استدعاء منشئ XmlSerializer سيؤدي إلى تجميع التعليمات البرمجية في وقت التشغيل وسيقوم بإنشاء ملف DLL مؤقت (في المجلد %temp%) مع التعليمات البرمجية لإجراء عملية إلغاء/التسلسل.

يمكنك مشاهدة الكود إذا أضفت الأسطر التالية إلى app.config:

  <system.diagnostics>
    <switches>
      <add name="XmlSerialization.Compilation" value="4"/>
    </switches>
  </system.diagnostics>

يستغرق هذا وقتًا طويلاً في المرة الأولى التي تقوم فيها بإجراء تسلسل لفصل دراسي ويحتاج إلى تعليمات برمجية ذات أذونات للتجميع والكتابة على القرص.

تتمثل إحدى طرق التغلب على ذلك في ترجمة ملفات DLL هذه مسبقًا باستخدام أداة sGen.exe التي تأتي مع VS 2005+.

انظر هنا لمزيد من المعلومات.

لست متأكدا إذا كان هناك أي قيود..ولكن كان هناك خطأ في تسرب الذاكرة في XmlSerialization في .NET 1.1، وكان عليك إنشاء كائن تسلسل ذاكرة التخزين المؤقت للتغلب على هذه المشكلة...في الواقع، لست متأكدًا مما إذا كان قد تم إصلاح هذه المشكلة في .net 2.0 أو الأحدث...

يمكن نظريًا تغذية أي فصل تكتبه من خلال XmlSerializer.ومع ذلك، فهو يتمتع فقط بإمكانية الوصول إلى الحقول العامة، ويجب تمييز الفئات بالسمات الصحيحة (على سبيل المثال.XmlAttribute).حتى في الإطار الأساسي، لا يدعم كل شيء XmlSerializer.System.Collections.Generic.Dictionary<> على سبيل المثال.

القيد الوحيد الذي يمكنني التفكير فيه هو أن XmlSerialization يتم إلغاء الاشتراك فيه؛وهذا يعني أن أي خصائص لفئة لا تريد تسلسلها يجب أن تكون مزينة بـ [XmlIgnore].على النقيض من ذلك مع DataContractSerializer حيث يتم الاشتراك في جميع الخصائص، يجب عليك الإعلان بوضوح عن سمات التضمين.هنا جيدة الكتابة.

يتم إجراء تسلسل للصور أو صفائفها الثنائية كنص مشفر باستخدام Base64 بواسطة XmlSerializer.

على سبيل المثال، لا يمكنك إجراء تسلسل للفئات التي تطبق واجهة IDictionary.

بالنسبة للمجموعات، يجب أن يكون لديهم طريقة Add تأخذ وسيطة واحدة.إذا كنت تحتاج فقط إلى تنسيق نصي وليس XML على وجه التحديد، فيمكنك تجربة JSON.لقد قمت بتطوير واحد لـ .NET، JsonExSerializer, ، وهناك آخرون متاحون أيضًا في http://www.json.org.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top