Force XML serialization to serialize readonly prop

2019-01-12 02:02发布

In C#, I have a class which has a derived property that should be serialized via XML. However, XML serialization (by default) doesn't serialize read=only properties. I can work around this by defining an empty setter like so:

public virtual string IdString
{
    get { return Id.ToString("000000"); }
    set { /* required for xml serialization */ }
}

But is there a cleaner more semantically correct way, short of writing my own ISerializable implementation?

3条回答
姐就是有狂的资本
2楼-- · 2019-01-12 02:17

Honestly this doesn't seem too bad to me as long as it is documented

You should probably throw an exception if the setter is actually called:

/// <summary>
/// Blah blah blah.
/// </summary>
/// <exception cref="NotSupportedException">Any use of the setter for this property.</exception>
/// <remarks>
/// This property is read only and should not be set.  
/// The setter is provided for XML serialisation.
/// </remarks>
public virtual string IdString
{
    get
    {
        return Id.ToString("000000");
    }
    set
    {
        throw new NotSupportedException("Setting the IdString property is not supported");
    }
}
查看更多
祖国的老花朵
3楼-- · 2019-01-12 02:24

To take the solution a little further to allow deserialization to work as well...

public class A
{
    private int _id = -1;

    public int Id
    {
        get { return _id; }
        set
        {
            if (_id < 0)
                throw new InvalidOperationException("...");

            if (value < 0)
                throw new ArgumentException("...");

            _id = value;
        }
    }
}

This will allow Id to be set exactly one time to a value greater than or equal to 0. Any attempts to set it after will result in InvalidOperationException. This means that XmlSerializer will be able to set Id during deserialization, but it will never be able to be changed after. Note that if the property is a reference type then you can just check for null.

This may not be the best solution if you have a lot of read-only properties to serialize/deserialize as it would require a lot of boilerplate code. However, I've found this to be acceptable for classes with 1-2 read-only properties.

Still a hack, but this is at least a little more robust.

查看更多
对你真心纯属浪费
4楼-- · 2019-01-12 02:30

In short, no. With XmlSerializer you can either implement IXmlSerializable (which is non-trivial), or write a basic DTO (that is fully read-write) and then translate from the DTO model to your main model.

Note that in some cases DataContractSerializer is a viable option, but it doesn't offer the same control over the XML. However, with DCS you can do:

[DataMember]
public int Id { get; private set; }
查看更多
登录 后发表回答