كيف يمكنني الحصول على XmlSerializer إجراء ترميز bools كما نعم / لا؟

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

  •  05-07-2019
  •  | 
  •  

سؤال

وأنا أرسل XML لبرنامج آخر، والذي يتوقع الأعلام منطقية ب "نعم" أو "لا"، بدلا من "صحيح" أو "كاذبة".

ولقد فئة محددة مثل:

[XmlRoot()]
public class Foo {
    public bool Bar { get; set; }
}

وعندما تسلسل ذلك، خرج لي تبدو مثل هذا:

<Foo><Bar>true</Bar></Foo>

ولكن أود أن يكون هذا:

<Foo><Bar>yes</Bar></Foo>

هل يمكنني القيام بذلك في وقت التسلسل؟ وأود أن تفضل عدم تضطر الى اللجوء الى هذا:

[XmlRoot()]
public class Foo {
    [XmlIgnore()]
    public bool Bar { get; set; }

    [XmlElement("Bar")]
    public string BarXml { get { return (Bar) ? "yes" : "no"; } }
}

لاحظ أن وأريد أيضا أن تكون قادرة على إلغاء تسلسل هذه البيانات مرة أخرى.

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

المحلول

حسنا، لقد كنت أبحث في هذا بعض أكثر. وهنا ما جئت مع:

// use this instead of a bool, and it will serialize to "yes" or "no"
// minimal example, not very robust
public struct YesNo : IXmlSerializable {

    // we're just wrapping a bool
    private bool Value;

    // allow implicit casts to/from bool
    public static implicit operator bool(YesNo yn) {
        return yn.Value;
    }
    public static implicit operator YesNo(bool b) {
        return new YesNo() {Value = b};
    }

    // implement IXmlSerializable
    public XmlSchema GetSchema() { return null; }
    public void ReadXml(XmlReader reader) {
        Value = (reader.ReadElementContentAsString() == "yes");
    }
    public void WriteXml(XmlWriter writer) {
        writer.WriteString((Value) ? "yes" : "no");
    }
}

وبعد ذلك يمكنني تغيير صفي فو لهذه:

[XmlRoot()]
public class Foo {      
    public YesNo Bar { get; set; }
}

لاحظ أنه بسبب YesNo هو castable ضمنا إلى bool (والعكس بالعكس)، لا يزال بإمكانك القيام بذلك:

Foo foo = new Foo() { Bar = true; };
if ( foo.Bar ) {
   // ... etc

وبعبارة أخرى، يمكنك التعامل معها مثل منطقي.

وw00t! أنه يسلسل لهذه:

<Foo><Bar>yes</Bar></Foo>

ووdeserializes أيضا بشكل صحيح.

وهناك ربما بعض طريقة للحصول على XmlSerializer بلدي ليلقي ظلالا من bools أنه واجه لYesNos كما يذهب تلقائيا - ولكن لم أجد حتى الآن. أي شخص؟

نصائح أخرى

وبسيطة جدا. استخدام خاصية البديلة. تطبيق XmlIgnore على الممتلكات الفعلية. والبديل هو سلسلة، ويجب استخدام السمة XmlElement أن يأخذ تجاوز اسم العنصر. تحديد اسم <م> الملكية الفعلية في التجاوز. يسلسل الممتلكات البديلة مختلف استنادا إلى قيمة العقار الفعلية. يجب أيضا توفير اضع لالبديل، واضعة يجب تعيين الخاصية الفعلية بشكل مناسب، لأي القيمة التي تسلسل. وبعبارة أخرى فإنه يحتاج إلى الذهاب في كلا الاتجاهين.

والقصاصة:

    public class SomeType 
    {

        [XmlElement]
        public int IntValue;

        [XmlIgnore]
        public bool Value;

        [XmlElement("Value")]
        public string Value_Surrogate {
            get { return (Value)? "Yes, definitely!":"Absolutely NOT!"; }
            set { Value= (value=="Yes, definitely!"); }
        }

    }

انقر هنا للحصول الكامل تحويل البرمجي مصدر سبيل المثال .

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

public YesOrNo DoYouLoveIt
{
    get { return boolToEvaluate ? YesOrNo.Yes : YesOrNo.No; }
}

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

وأنا استخدم الطريقة الممتلكات، ولكن بدلا من فحص لمعرفة ما إذا كانت السلسلة تساوي نعم أو لا، أنا أفضل للتحقق مما إذا تبدأ السلسلة مع (قضية حساسة) "YT1". يسمح هذا الملف لاحتواء صحيح، صحيح، تي، T، Y، Y، نعم، نعم، 1، الخ كل ما ستقوم بتقييم إلى true. في حين أستطيع تحديد أن كاذبة كاذبة، كاذبة، و، F، N، N، لا، لا، 0، وما إلى ذلك، كل ما لا يتطابق مع صحيح لا يزال يقيم إلى false.

والمثال الممتلكات الخاصة بك وربما كان أبسط طريقة يمكنك أن تفعل ذلك. إذا كان يساعد، وأعتقد أنك لا تحتاج إلى جعلها الممتلكات العامة، منذ السمة تنفذ ISerializable على الطبقة وراء ظهرك. لتمكين إلغاء التسلسل، يجب أن تكون قادرة على تنفيذ فقط set { Bar = value == "yes"; }

وBlorgbeard: إذا كان لديك أكثر من واحد من هذه الفئات YesNo في فئة الكائن، تأكد من قراءة العنصر بالكامل.

public void ReadXml(XmlReader reader)
{
    string element = reader.ReadOuterXml();
    int startIndex = element.IndexOf('>') + 1;
    int length = element.LastIndexOf('<') - startIndex;

    string text = (element.Substring(startIndex, length).ToLowerInvariant();

    Value = (text == "yes");
}

وإلا هذا قد يسبب مشاكل.

<اقتباس فقرة>   

وأسلوب ReadXml يجب إعادة تكوين الكائن باستخدام المعلومات التي تم كتابتها بواسطة الأسلوب WriteXml.

     

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

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

scroll top