سؤال

باستخدام C# .NET 2.0، لدي فئة بيانات مركبة تحتوي على [Serializable] صفة عليه.أنا أقوم بإنشاء XMLSerializer فئة وتمرير ذلك إلى المنشئ:

XmlSerializer serializer = new XmlSerializer(typeof(DataClass));

أحصل على استثناء قائلا:

حدث خطأ يعكس النوع.

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

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

المحلول

انظر إلى الاستثناء الداخلي الذي تحصل عليه.سيخبرك بالمجال/الخاصية التي تواجه مشكلة في إجراء تسلسل لها.

يمكنك استبعاد الحقول/الخصائص من تسلسل XML عن طريق تزيينها بالملحق [XmlIgnore] يصف.

لا أعتقد ذلك XmlSerializer يستخدم [Serializable] السمة، لذلك أشك في أن هذه هي المشكلة.

نصائح أخرى

تذكر أن الفئات المتسلسلة يجب أن تكون افتراضية (أي:بدون معلمات) المنشئات.إذا لم يكن لديك مُنشئ على الإطلاق، فلا بأس؛ولكن إذا كان لديك مُنشئ ذو معلمة، فستحتاج إلى إضافة المعلمة الافتراضية أيضًا.

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

يستخدم كل من "الأنواع BaseNamespace.Class1" و"BaseNamespace.SubNamespace.Class1" اسم نوع XML، "Class1"، من مساحة الاسم ''.استخدم سمات XML لتحديد اسم XML فريد و/أو مساحة اسم للنوع.

حيث BaseNamespace.SubNamespace.Class1 هي فئة فرعية من BaseNamespace.Class1.

ما كنت بحاجة إلى فعله هو إضافة سمة إلى إحدى الفئات (لقد أضفتها إلى الفئة الأساسية):

[XmlType("BaseNamespace.Class1")]

ملحوظة:إذا كان لديك المزيد من طبقات الفئات، فستحتاج إلى إضافة سمة إليها أيضًا.

كن على علم بذلك أيضًا XmlSerializer لا يمكن إجراء تسلسل للخصائص المجردة ..انظر سؤالي هنا (الذي قمت بإضافة رمز الحل إليه)..

تسلسل XML والأنواع الموروثة

الأسباب الأكثر شيوعًا بالنسبة لي:

 - the object being serialized has no parameterless constructor
 - the object contains Dictionary
 - the object has some public Interface members

يجب أن تكون جميع الكائنات الموجودة في الرسم البياني للتسلسل قابلة للتسلسل.

منذ XMLSerializer هو صندوق أسود، تحقق من هذه الروابط إذا كنت تريد تصحيح الأخطاء بشكل أكبر في عملية التسلسل.

تغيير مكان إخراج XmlSerializer للتجميعات المؤقتة

كيف:تصحيح الأخطاء في مجموعة .NET XmlSerializer المُنشأة

إذا كنت بحاجة إلى التعامل مع سمات محددة (أي.قاموس، أو أي فئة)، يمكنك تنفيذ IXmlSerialialable الواجهة، والتي سوف تتيح لك المزيد من الحرية على حساب المزيد من الترميز المطول.

public class NetService : IXmlSerializable
{
    #region Data

        public string Identifier = String.Empty;

        public string Name = String.Empty;

        public IPAddress Address = IPAddress.None;
        public int Port = 7777;

    #endregion

    #region IXmlSerializable Implementation

        public XmlSchema GetSchema() { return (null); }

        public void ReadXml(XmlReader reader)
        {
            // Attributes
            Identifier = reader[XML_IDENTIFIER];
            if (Int32.TryParse(reader[XML_NETWORK_PORT], out Port) == false)
            throw new XmlException("unable to parse the element " + typeof(NetService).Name + " (badly formatted parameter " + XML_NETWORK_PORT);
            if (IPAddress.TryParse(reader[XML_NETWORK_ADDR], out Address) == false)
            throw new XmlException("unable to parse the element " + typeof(NetService).Name + " (badly formatted parameter " + XML_NETWORK_ADDR);
        }

        public void WriteXml(XmlWriter writer)
        {
            // Attributes
            writer.WriteAttributeString(XML_IDENTIFIER, Identifier);
            writer.WriteAttributeString(XML_NETWORK_ADDR, Address.ToString());
            writer.WriteAttributeString(XML_NETWORK_PORT, Port.ToString());
        }

        private const string XML_IDENTIFIER = "Id";

        private const string XML_NETWORK_ADDR = "Address";

        private const string XML_NETWORK_PORT = "Port";

    #endregion
}

هناك مثيرة للاهتمام شرط, ، والتي تُظهر طريقة أنيقة لتطبيق طريقة متطورة "لتوسيع" XmlSerializer.


المقال يقول:

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

لأن هذا، أقترح عليك تنفيذ بنفسك IXmlSerializable الطبقات، من أجل تجنب الكثير من التطبيقات المعقدة.

... قد يكون من السهل تنفيذ عاداتنا XmlSerializer فئة باستخدام الانعكاس.

لقد اكتشفت أن فئة القاموس في .Net 2.0 غير قابلة للتسلسل باستخدام XML، ولكنها تتسلسل بشكل جيد عند استخدام التسلسل الثنائي.

لقد وجدت عملاً حولها هنا.

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

    [System.Xml.Serialization.XmlElementAttribute(Order = XX)]

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

لقد اعتقدت أيضًا أن السمة القابلة للتسلسل يجب أن تكون على الكائن ولكن ما لم أكن مستجدًا تمامًا (أنا في منتصف جلسة ترميز في وقت متأخر من الليل) فإن ما يلي يعمل من SnippetCompiler:

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

public class Inner
{
    private string _AnotherStringProperty;
    public string AnotherStringProperty 
    { 
      get { return _AnotherStringProperty; } 
      set { _AnotherStringProperty = value; } 
    }
}

public class DataClass
{
    private string _StringProperty;
    public string StringProperty 
    { 
       get { return _StringProperty; } 
       set{ _StringProperty = value; } 
    }

    private Inner _InnerObject;
    public Inner InnerObject 
    { 
       get { return _InnerObject; } 
       set { _InnerObject = value; } 
    }
}

public class MyClass
{

    public static void Main()
    {
        try
        {
            XmlSerializer serializer = new XmlSerializer(typeof(DataClass));
            TextWriter writer = new StreamWriter(@"c:\tmp\dataClass.xml");
            DataClass clazz = new DataClass();
            Inner inner = new Inner();
            inner.AnotherStringProperty = "Foo2";
            clazz.InnerObject = inner;
            clazz.StringProperty = "foo";
            serializer.Serialize(writer, clazz);
        }
        finally
        {
            Console.Write("Press any key to continue...");
            Console.ReadKey();
        }
    }

}

أتصور أن XmlSerializer يستخدم الانعكاس على الخصائص العامة.

لقد حصلت للتو على نفس الخطأ واكتشفت أن خاصية النوع IEnumerable<SomeClass> كانت المشكلة.يبدو أنه IEnumerable لا يمكن إجراء تسلسل مباشرة.

بدلا من ذلك، يمكن للمرء أن يستخدم List<SomeClass>.

كان لدي موقف حيث كان الترتيب هو نفسه بالنسبة لعنصرين متتاليين

[System.Xml.Serialization.XmlElementAttribute(IsNullable = true, Order = 0, ElementName = "SeriousInjuryFlag")]

....بعض التعليمات البرمجية ...

[System.Xml.Serialization.XmlElementAttribute(IsNullable = true, Order = 0, ElementName = "AccidentFlag")]

عندما قمت بتغيير الكود لزيادة الترتيب بمقدار واحد لكل خاصية جديدة في الفصل، اختفى الخطأ.

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

لقد تم استخدام NetDataSerialiser الفصل لسلسلة فصول المجال الخاصة بي. فئة NetDataContractSerializer.

تتم مشاركة فئات المجال بين العميل والخادم.

[System.Xml.Serialization.XmlElementAttribute("strFieldName"، النموذج = System.Xml.Schema.XmlSchemaForm.Unqualified)]

//أو

xmlignore] String [] strfielsname {get ؛ set ؛}

واجهت نفس المشكلة وفي حالتي كان الكائن يحتوي على ReadOnlyCollection.يجب أن تقوم المجموعة بتنفيذ طريقة الإضافة لتكون قابلة للتسلسل.

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