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

Chr*_*ris 33 c# xml-serialization

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

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

但是,除了编写自己的ISerializable实现之外,还有一种更清晰,语义更正确的方法吗?

Jus*_*tin 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");
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 这不会导致反序列化失败,只是因为这个异常然后被抛出? (8认同)
  • @primfaktor是的,但正如我所理解的那样重要的问题(它永远不会被反序列化).如果这不是理想的行为,你可以在setter中什么也不做,甚至解析字符串并设置`Id`属性(可能只有在它尚未设置的情况下). (2认同)

Mar*_*ell 14

简而言之,没有.有了XmlSerializer你可以实现IXmlSerializable(这是不平凡的),或者写一个基本的DTO(即完全读写),然后从DTO模式,你的主模型转换.

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

[DataMember]
public int Id { get; private set; }
Run Code Online (Sandbox Code Playgroud)

  • `IXmlSerializable`实际上对这个问题非常有效,特别是如果你只是序列化而不是反序列化,并不是那么难.看看这个:http://www.codeproject.com/Articles/43237/How-to-Implement-IXmlSerializable-Correctly (4认同)

Yai*_*adt 6

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

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

如果有人不小心使用了 setter,这将会出错。