我正试图找到一种方法来改变属性的序列化行为。
假设我有这样的情况:
[Serializable]
public class Record
{
public DateTime LastUpdated {get; set; }
// other useful properties ...
}
public class EmployeeRecord : Record
{
public string EmployeeName {get; set; }
// other useful properties ...
}
现在我要序列化EmployeeRecord。我不希望序列化Record类中的LastUpdated属性。 (我确实希望在序列化记录时序列化LastUpdated)。
首先,我尝试使用 new 关键字隐藏LastUpdated属性,然后添加XmlIgnore属性:
public class EmployeeRecord : Record
{
public string EmployeeName {get; set; }
[XmlIgnore]
public new DateTime LastUpdated {get; set; }
// other useful properties ...
}
但那没用。然后我尝试将基础LastUpdated虚拟化并覆盖它,保留属性:
[Serializable]
public class Record
{
public virtual DateTime LastUpdated {get; set; }
// other useful properties ...
}
public class EmployeeRecord : Record
{
public string EmployeeName {get; set; }
[XmlIgnore]
public override DateTime LastUpdated {get; set; }
// other useful properties ...
}
这也不起作用。在两次尝试中,LastUpdated忽略了XmlIgnore属性,并愉快地开展了序列化业务。
有没有办法让我想要做的事情发生?
答案 0 :(得分:17)
首先,[Serializable] attr与XmlSerializer无关。那是一只红鲱鱼。 [Serializable]对System.Runtime.Serialization有意义,而XmlSerializer则存在于System.Xml.Serialization中。如果您使用[Serializable]和您的成员使用[XmlIgnore]装饰您的课程,那么您可能会混淆自己或您的代码的其他读者。
.NET中的XmlSerialization非常灵活。取决于序列化的完成方式,直接由您或间接完成,比如说Web服务运行时 - 您有不同的方法来控制事物。
一种选择是使用 propertyName 指定模式在XML序列化中打开或关闭属性。假设你有这段代码:
public class TypeA
{
public DateTime LastModified;
[XmlIgnore]
public bool LastModifiedSpecified;
}
然后,如果实例中的LastModifiedSpecified为false,则不会为该实例序列化LastModified字段。在类型的构造函数中,可以将LastModifiedSpecified设置为在基类型中始终为true,并在派生类型中始终为false。实际的布尔值 - LastModifiedSpecified - 永远不会被序列化,因为它被标记为XmlIgnore。
这个小技巧记录在案here。
您的另一个选择是使用XmlAttributeOverrides,这是一种动态提供XML序列化属性集的方法(如XmlElementAttribute,XmlIgnoreAttribute,XmlRootAttribute等等) - 在运行时动态地将这些属性提供给序列化程序。 XmlSerializer不是检查这些属性的类型本身,而是遍历提供给其构造函数的覆盖属性列表。
var overrides = new XmlAttributeOverrides();
// ....fill the overrides here....
// create a new instance of the serializer specifying overrides
var s1 = new XmlSerializer(typeof(Foo), overrides);
// serialize as normal, here.
更详细地说明here。
在您的情况下,您将提供XmlIgnoreAttribute作为覆盖,但仅在序列化派生类型时提供。 (或其他)只有在直接实例化XmlSerializer时才有效 - 当运行时隐式执行序列化时,它不起作用,就像Web服务一样。
干杯!
答案 1 :(得分:8)
我能想到的最好的......
[Serializable]
public class Record
{
public DateTime LastUpdated {get; set; }
public virtual bool ShouldSerializeLastUpdated() {return true;}
// other useful properties ...
}
public class EmployeeRecord : Record
{
public string EmployeeName {get; set; }
public override bool ShouldSerializeLastUpdated() {return false;}
// other useful properties ...
}
基本上,XmlSerializer
尊重一些模式; public bool ShouldSerialize*()
和public bool *Specified {get;set;}
(请注意,您应将*Specified
标记为[XmlIgnore]
......)。
不太优雅,我会批准;但是XmlSerializer
只关注公众成员,所以你甚至无法隐藏它们([EditorBrowsable(EditorBrowsableState.Never), Browsable(false)]
之外)。