强制XML序列化以序列化readonly属性

时间:2011-04-07 17:50:37

标签: c# xml-serialization

在C#中,我有一个类,它有一个派生属性,应该通过XML序列化。但是,XML序列化(默认情况下)不会序列化read = only属性。我可以通过定义一个空的setter来解决这个问题:

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

但是,如果没有编写我自己的ISerializable实现,是否有更清晰的语义更正确的方法?

4 个答案:

答案 0 :(得分:19)

老实说,只要记录在案,这对我来说似乎并不太糟糕

如果实际调用了setter,你应该抛出异常:

/// <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");
    }
}

答案 1 :(得分:14)

简而言之,没有。使用XmlSerializer,您可以实现IXmlSerializable(这是非平凡的),或者编写基本的DTO(完全读写),然后从DTO模型转换为主模型。

请注意,在某些情况下 DataContractSerializer是一个可行的选项,但它不提供对XML的相同控制。但是,使用DCS,您可以:

[DataMember]
public int Id { get; private set; }

答案 2 :(得分:1)

进一步采取解决方案以允许反序列化工作......

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;
        }
    }
}

这将允许Id恰好一次设置为大于或等于0的值。任何尝试将其设置的结果都将导致InvalidOperationException。这意味着XmlSerializer将能够在反序列化期间设置Id,但之后永远无法更改。请注意,如果属性是引用类型,那么您只需检查null。

如果您有许多只读属性来序列化/反序列化,这可能不是最佳解决方案,因为它需要大量的样板代码。但是,我发现这对于具有1-2个只读属性的类来说是可以接受的。

仍然是一个黑客,但这至少是更强大。

答案 3 :(得分:1)

对于C#8,允许废弃set,因此您可以这样做:

public virtual string IdString
{
    get { return Id.ToString("000000"); }
    [Obsolete("Only used for xml serialization", error: true)]
    set { throw new NotSupportedException(); }
}

如果有人不小心使用了二传手,就会出错。