简体   繁体   English

使用属性覆盖属性

[英]Overriding a property with an attribute

I'm trying to find a way to change the serialization behavior of a property. 我正试图找到一种方法来改变属性的序列化行为。

Lets say I have a situation like this: 可以说我有这样的情况:

[Serializable]
public class Record
{
   public DateTime LastUpdated {get; set; }

   // other useful properties ...
}

public class EmployeeRecord : Record
{
   public string EmployeeName {get; set; }

   // other useful properties ...
}

Now I want to serialize EmployeeRecord. 现在我想序列化EmployeeRecord。 I don't want the LastUpdated property from the Record class to be serialized. 我不希望序列化Record类中的LastUpdated属性。 (I do want LastUpdated to be serialized when I serialize Record, though). (我确实希望在序列化Record时序列化LastUpdated)。

First I tried hiding the LastUpdated property by using the new keyword and then adding the XmlIgnore attribute: 首先,我尝试使用new关键字隐藏LastUpdated属性,然后添加XmlIgnore属性:

public class EmployeeRecord : Record
{
   public string EmployeeName {get; set; }

   [XmlIgnore]
   public new DateTime LastUpdated {get; set; }
   // other useful properties ...
}

But that didn't work. 但那没用。 Then I tried making the base LastUpdated virtual and overriding it, keeping the attribute: 然后我尝试将基础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 ...
}

This didn't work either. 这也不起作用。 In both attempts the LastUpdated ignored the XmlIgnore attribute and happily went about its business of serializing. 在这两次尝试中,LastUpdated都忽略了XmlIgnore属性,并愉快地开展了序列化业务。

Is there a way to make what I'm trying to do happen? 有没有办法让我正在尝试做的事情发生?

First, the [Serializable] attr has nothing to do with the XmlSerializer. 首先,[Serializable] attr与XmlSerializer无关。 That is a red herring. 那是一只红鲱鱼。 [Serializable] is meaningful to System.Runtime.Serialization, while the XmlSerializer lives in System.Xml.Serialization. [Serializable]对System.Runtime.Serialization有意义,而XmlSerializer则存在于System.Xml.Serialization中。 If you are decorating your class with [Serializable] and your members with [XmlIgnore] then you are probably confusing yourself or other readers of your code. 如果您使用[Serializable]和您的成员使用[XmlIgnore]装饰您的课程,那么您可能会混淆自己或您的代码的其他读者。

XmlSerialization in .NET is very flexible. .NET中的XmlSerialization非常灵活。 Depending on how the serialization is being done, directly by you or indirectly, let's say by the web services runtime - you have different ways to control things. 取决于序列化的完成方式,直接由您或间接完成,比如说Web服务运行时 - 您有不同的方法来控制事物。

One option is to use the propertyName Specified pattern to turn ON or OFF the property in XML Serialization. 一种选择是使用propertyName Specified模式在XML Serialization中打开或关闭属性。 Suppose you have this code: 假设你有这个代码:

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

Then, if LastModifiedSpecified is false in an instance, the LastModified field will not be serialized for that instance. 然后,如果实例中的LastModifiedSpecified为false,则不会为该实例序列化LastModified字段。 In the constructor for your type, you can set LastModifiedSpecified to always be true in the base type, and always false in the derived type. 在类型的构造函数中,可以将LastModifiedSpecified设置为在基类型中始终为true,并在派生类型中始终为false。 The actual boolean - LastModifiedSpecified - never gets serialized because it is marked XmlIgnore. 实际的布尔值 - LastModifiedSpecified - 永远不会被序列化,因为它被标记为XmlIgnore。

This little trick is documented here . 这里记录这个小技巧。

Your other option is to use XmlAttributeOverrides, which is a way of dynamically providing the set of XML serialization attributes (like XmlElementAttribute, XmlIgnoreAttribute, XmlRootAttribute, and so on...) - dynamically providing those attributes to the serializer at runtime. 您的另一个选择是使用XmlAttributeOverrides,这是一种动态提供XML序列化属性集的方法(如XmlElementAttribute,XmlIgnoreAttribute,XmlRootAttribute等等) - 在运行时动态地将这些属性提供给序列化程序。 The XmlSerializer, instead of inspecting the type itself for those attributes, will just walk through the list of override attributes provided to its constructor. 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.

This is illustrated in more detail here . 这在此处更详细地说明。

In your case, you would provide an XmlIgnoreAttribute as an override, but only when serializing the derived type. 在您的情况下,您将提供XmlIgnoreAttribute作为覆盖,但仅在序列化派生类型时。 (or whatever) This works only when you directly instantiate the XmlSerializer - it won't work when serialization is done implicitly by the runtime, as with web services. (或其他)只有在直接实例化XmlSerializer时才有效 - 当运行时隐式执行序列化时,它不起作用,就像Web服务一样。

Cheers! 干杯!

The best I can think of... 我能想到的最好的......

[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 ...
}

Basically, there are a few patterns that XmlSerializer respects; 基本上, XmlSerializer有一些模式; public bool ShouldSerialize*() , and public bool *Specified {get;set;} (note you should mark *Specified with [XmlIgnore] too...). public bool ShouldSerialize*()public bool *Specified {get;set;} (注意你应该标记*Specified[XmlIgnore] *Specified ...)。

Not very elegant, I'll grant; 不太优雅,我会授予; but XmlSerializer only looks at public members, so you can't even hide them (short of [EditorBrowsable(EditorBrowsableState.Never), Browsable(false)] ). 但是XmlSerializer只查看公共成员,因此你甚至无法隐藏它们(缺少[EditorBrowsable(EditorBrowsableState.Never), Browsable(false)] )。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM