Serialization in XML via DataContract: custom output?

I have my own class of fractions, which I use throughout my project. It is simple, it consists of one constructor, takes two ints and saves them. I would like to use the DataContractSerializer to serialize my objects used in my project, some of which include Fractions fields. Ideally, I would like to serialize such objects as follows:

<Object>
    ...
    <Frac>1/2</Frac> // "1/2" would get converted back into a Fraction on deserialization.
    ...
</Object>

In contrast to this:

<Object>
    ...
    <Frac>
        <Numerator>1</Numerator>
        <Denominator>2</Denominator>
    </Frac>
    ...
</Object>

Is there a way to do this using DataContracts?

, XML ( , ) , .

. , ( readonly), , Fraction .

+5
5

, Frac, DataMember, , , , :

[DataContract]
public class MyObject {
    Int32 _Numerator;
    Int32 _Denominator;
    public MyObject(Int32 numerator, Int32 denominator) {
        _Numerator = numerator;
        _Denominator = denominator;
    }
    public Int32 Numerator {
        get { return _Numerator; }
        set { _Numerator = value; }
    }
    public Int32 Denominator {
        get { return _Denominator; }
        set { _Denominator = value; }
    }
    [DataMember(Name="Frac")]
    public String Fraction {
        get { return _Numerator + "/" + _Denominator; }
        set {
            String[] parts = value.Split(new char[] { '/' });
            _Numerator = Int32.Parse(parts[0]);
            _Denominator = Int32.Parse(parts[1]);
        }
    }
}
+6

DataContractSerializer IXmlSerializable DataContractAttribute. XML ... .

public class Fraction: IXmlSerializable 
{
    private Fraction()
    {
    }
    public Fraction(int numerator, int denominator)
    {
        this.Numerator = numerator;
        this.Denominator = denominator;
    }
    public int Numerator { get; private set; }
    public int Denominator { get; private set; }

    public XmlSchema GetSchema()
    {
        throw new NotImplementedException();
    }

    public void ReadXml(XmlReader reader)
    {
        var content = reader.ReadInnerXml();
        var parts = content.Split('/');
        Numerator = int.Parse(parts[0]);
        Denominator = int.Parse(parts[1]);
    }

    public void WriteXml(XmlWriter writer)
    {
        writer.WriteRaw(this.ToString());
    }

    public override string ToString()
    {
        return string.Format("{0}/{1}", Numerator, Denominator);
    }
}
[DataContract(Name = "Object", Namespace="")]
public class MyObject
{
    [DataMember]
    public Fraction Frac { get; set; }
}

class Program
{
    static void Main(string[] args)
    {
        var myobject = new MyObject
        {
            Frac = new Fraction(1, 2)
        };

        var dcs = new DataContractSerializer(typeof(MyObject));

        string xml = null;
        using (var ms = new MemoryStream())
        {
            dcs.WriteObject(ms, myobject);
            xml = Encoding.UTF8.GetString(ms.ToArray());
            Console.WriteLine(xml);
            // <Object><Frac>1/2</Frac></Object>
        }

        using (var ms = new MemoryStream(Encoding.UTF8.GetBytes(xml)))
        {
            ms.Position = 0;
            var obj = dcs.ReadObject(ms) as MyObject;

            Console.WriteLine(obj.Frac);
            // 1/2
        }
    }
}
+5

MSDN IDataContractSurrogate, :

, DataContractSerializer , XML.

, -. , XML .

+3

DataContractSerializer, , . , . , [On (De) Serializ (ed | ing)] - , int , . , DataContractSerializer .

, :

[DataContract]
public class Fraction
{
    [DataMember(Name = "Frac")]
    private string serialized;

    public int Numerator { get; private set; }
    public int Denominator { get; private set; }

    [OnSerializing]
    public void OnSerializing(StreamingContext context)
    {
        // This gets called just before the DataContractSerializer begins.
        serialized = Numerator.ToString() + "/" + Denominator.ToString();
    }

    [OnDeserialized]
    public void OnDeserialized(StreamingContext context)
    {
        // This gets called after the DataContractSerializer finishes its work
        var nums = serialized.Split("/");
        Numerator = int.Parse(nums[0]);
        Denominator = int.Parse(nums[1]);
    }
}
+1

To do this, you need to switch to XMLSerializer. The DataContractSerializer is a bit more restrictive in terms of the ability to customize the output.

0
source

All Articles