开发者

Using .NET XmlSerializer with get properties and setter functions

I'm trying to use XmlSerializer from C# to save out a class that has some values that are read by properties (the code being just a simple retrieval of field value) but set by setter functions (since there is a delegate called if the value changes).

What I'm currently doing is this sort of thing. The intended use is to use the InT property to read the value, and use SetInT to set it. Setting it has side-effects, so a method is more appropriate than a property here. XmlSerializationOnly_InT exists solely for the benefit of the XmlSerializer (hence the name), and shouldn't be used by normal code.

class X
{
    public double InT
    {
        get { return _inT; }
    }

    public void SetInT(double newInT)
    {
        if (newInT != _inT)
        {
            _inT = newInT;
            Changed();//includes delegate call; potentially expensive
        }
    }

    private double _inT;

    // not called by normal code, as the property set is not just a simple
    // field set or two.
    [XmlElement(ElementName = "InT")]
    public double XmlSerializationOnly_InT
    {
        get { return InT; }
        set { SetInT(value); }
    }
}

This works, it's easy enough to do, and the XML file looks like you'd expect. It's manual labour though, and a bit ugly, so I'm only somewhat satisfied. What I'd really like is to be able to tell the XML serialization to read the value using the property, and set it using the setter function. Then I wouldn't need XmlSerializationOnly_InT at all.

I seem to be following standard practise by distinguishing between property sets and setter functions in this way, so I'm sure I'm not the only person to have encountered this (though google suggests开发者_开发百科 I might be). What have others done in this situation? Is there some easy way to persuade the XmlSerializer to handle this sort of thing better? If not, is there perhaps some other easy way to do it?


EDIT:
I would really just make the setter function part of the property. If you want you could have the setter trigger an event and call the function in the event.

// A delegate type for hooking up change notifications.
public delegate void ChangedEventHandler(object sender, EventArgs e);

class X
{
    private double _inT;

    // An event that clients can use to be notified whenever the
    // elements of the list change.
    public event ChangedEventHandler InTChanged;
    // Invoke the Changed event; called whenever list changes

    protected virtual void OnChanged(EventArgs e) 
    {
        if (InTChanged != null)
            InTChanged(this, e);
    }
    public double InT
    {
        get { return InT; }
        set
        {
            _inT = newInT;

            //Invoke InTChanged event here
            OnChanged(EventArgs.Empty);
        }
    }
}

Otherwise you could just right your own serialize and deserialize functions:

class X
{
    public void SetInT(double newInT)
    {
        if (newInT != _inT)
        {
            _inT = newInT;
            Changed();//includes delegate call; potentially expensive
        }
    }

    private double _inT;

    public double InT
    {
        get { return InT; }
    }
    public XElement SerializeX()
    {
        XElement serializedItems = new XElement("X",
            new XElement("InT", this._inT),
            new XElement("OtherProperty1", this.OtherProperty1),
            new XElement("OtherProperty2", this.OtherProperty2));
        return serializedItems;
    }
    public void DeserializeX(XElement itemXML)
    {
        this._inT = Double.Parse(itemXML.Element("InT").Value,
            CultureInfo.InvariantCulture);
        this.OtherProperty1 = Double.Parse(
            itemXML.Element("OtherProperty1").Value,
            CultureInfo.InvariantCulture);
        this.OtherProperty2 = Double.Parse(
            itemXML.Element("OtherProperty2").Value,
            CultureInfo.InvariantCulture);
    }
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜