Сериализация типа в XML из .NET

У меня есть этот тип С# 4.0

public class DecimalField
{
    public decimal Value { get; set; }
    public bool Estimate { get; set; }
}

Я хочу использовать XmlSerializer для сериализации типа в

<Val Estimate="true">123</Val>

В идеале я хочу опустить атрибут Estimate, если его значение равно false. Допустимо изменение Estimate на логическое значение, допускающее значение NULL.

Какие атрибуты/реализации необходимы для перехода от этого типа к этому XML-представлению?

Спасибо.


person user1044169    schedule 13.08.2012    source источник
comment
я думаю, что использование некоторых атрибутов сделает это. хотя не уверен, что это за атрибуты.   -  person DarthVader    schedule 13.08.2012


Ответы (3)


Не уверен, что вы можете вывести Estimate условно только с атрибутами. Но вы определенно можете реализовать IXmlSerializable и проверить значение Estimate внутри метода WriteXml.

Вот пример

person Volma    schedule 13.08.2012

Условное исключение Estimate потребовало бы большого количества кода. Я бы не пошел таким путем.

XmlWriter writer = XmlWriter.Create(stream, new XmlWriterSettings() { OmitXmlDeclaration = true });

var ns = new XmlSerializerNamespaces();
ns.Add("", "");

XmlSerializer xml = new XmlSerializer(typeof(DecimalField));

xml.Serialize(writer, obj, ns);

-

[XmlRoot("Val")]
public class DecimalField
{
    [XmlText]
    public decimal Value { get; set; }
    [XmlAttribute]
    public bool Estimate { get; set; }
}

Вы также можете вручную сериализовать свой класс, используя Linq2Xml.

List<XObject> list = new List<XObject>();
list.Add(new XText(obj.Value.ToString()));
if (obj.Estimate) list.Add(new XAttribute("Estimate", obj.Estimate));

XElement xElem = new XElement("Val", list.ToArray());

xElem.Save(stream);
person L.B    schedule 13.08.2012

Это настолько близко, насколько это возможно (атрибут Estimate всегда включен) без реализации IXmlSerializable:

[XmlRoot("Val")]
public class DecimalField
{
    [XmlText()]
    public decimal Value { get; set; }
    [XmlAttribute("Estimate")]
    public bool Estimate { get; set; }
}

С IXmlSerializable ваш класс выглядит так:

[XmlRoot("Val")]
public class DecimalField : IXmlSerializable
{
    public decimal Value { get; set; }
    public bool Estimate { get; set; }

    public void WriteXml(XmlWriter writer)
    {
        if (Estimate == true)
        {
            writer.WriteAttributeString("Estimate", Estimate.ToString());
        }

        writer.WriteString(Value.ToString());
    }

    public void ReadXml(XmlReader reader)
    {
        if (reader.MoveToAttribute("Estimate") && reader.ReadAttributeValue())
        {
            Estimate = bool.Parse(reader.Value);
        }
        else
        {
            Estimate = false;
        }

        reader.MoveToElement();
        Value = reader.ReadElementContentAsDecimal();
    }

    public XmlSchema GetSchema()
    {
        return null;
    }
}

Вы можете протестировать свой класс следующим образом:

    XmlSerializer xs = new XmlSerializer(typeof(DecimalField));

    string serializedXml = null;
    using (StringWriter sw = new StringWriter())
    {
        DecimalField df = new DecimalField() { Value = 12.0M, Estimate = false };
        xs.Serialize(sw, df);
        serializedXml = sw.ToString();
    }

    Console.WriteLine(serializedXml);

    using (StringReader sr = new StringReader(serializedXml))
    {
        DecimalField df = (DecimalField)xs.Deserialize(sr);

        Console.WriteLine(df.Estimate);
        Console.WriteLine(df.Value);
    }
person JamieSee    schedule 13.08.2012