使用属性覆盖属性

我正试图找到一种方法来改变属性的序列化行为。

可以说我有这样的情况:

[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属性。 (我确实希望在序列化Record时序列化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属性,并愉快地开展了序列化业务。

有没有办法让我正在尝试做的事情发生?

首先,[Serializable] attr与XmlSerializer无关。 那是一只红鲱鱼。 [Serializable]对System.Runtime.Serialization有意义,而XmlSerializer则存在于System.Xml.Serialization中。 如果您使用[Serializable]和您的成员[XmlIgnore]装饰您的课程,那么您可能会困惑自己或您的代码的其他读者。

.NET中的XmlSerialization非常灵活。 根据序列化的完成方式,直接由您或间接完成,比如Web服务运行时 – 您可以通过不同的方式来控制事物。

一种选择是使用propertyName Specified模式在XML Serialization中打开或关闭属性。 假设你有这个代码:

 public class TypeA { public DateTime LastModified; [XmlIgnore] public bool LastModifiedSpecified; } 

然后,如果实例中的LastModifiedSpecified为false,则不会为该实例序列化LastModified字段。 在类型的构造函数中,可以将LastModifiedSpecified设置为在基类型中始终为true,并在派生类型中始终为false。 实际的布尔值 – LastModifiedSpecified – 永远不会被序列化,因为它被标记为XmlIgnore。

这里记录了这个小技巧。

您的另一个选择是使用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. 

这在此处更详细地说明。

在您的情况下,您将提供XmlIgnoreAttribute作为覆盖,但仅在序列化派生类型时。 (或其他)只有在直接实例化XmlSerializer时才有效 – 当运行时隐式执行序列化时,它将无法工作,就像Web服务一样。

干杯!

我能想到的最好的……

 [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] *Specified …)。

不太优雅,我会批准; 但XmlSerializer只查看公共成员,因此你甚至无法隐藏它们(缺少[EditorBrowsable(EditorBrowsableState.Never), Browsable(false)] )。