C# 用属性覆盖属性
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/592671/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Overriding a property with an attribute
提问by Sailing Judo
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. I don't want the LastUpdated property from the Record class to be serialized. (I do want LastUpdated to be serialized when I serialize Record, though).
现在我想序列化EmployeeRecord。我不希望 Record 类中的 LastUpdated 属性被序列化。(不过,我确实希望在序列化 Record 时将 LastUpdated 序列化)。
First I tried hiding the LastUpdated property by using the newkeyword 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?
有没有办法让我想做的事情发生?
采纳答案by Cheeso
First, the [Serializable] attr has nothing to do with the XmlSerializer. That is a red herring. [Serializable] is meaningful to System.Runtime.Serialization, while the XmlSerializer lives in 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] attr 与 XmlSerializer 无关。那是一条红鲱鱼。[Serializable] 对 System.Runtime.Serialization 有意义,而 XmlSerializer 存在于 System.Xml.Serialization 中。如果您使用 [Serializable] 装饰您的类,并使用 [XmlIgnore] 装饰您的成员,那么您可能会混淆您自己或您的代码的其他读者。
XmlSerialization in .NET is very flexible. 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.
.NET 中的 XmlSerialization 非常灵活。根据序列化的完成方式,直接由您完成或间接由 Web 服务运行时完成 - 您有不同的方式来控制事物。
One option is to use the propertyNameSpecified pattern to turn ON or OFF the property in XML Serialization. Suppose you have this code:
一种选择是使用propertyNameSpecified 模式在 XML 序列化中打开或关闭属性。假设您有以下代码:
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. 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. The actual boolean - LastModifiedSpecified - never gets serialized because it is marked XmlIgnore.
然后,如果实例中的 LastModifiedSpecified 为 false,则不会为该实例序列化 LastModified 字段。在您的类型的构造函数中,您可以将 LastModifiedSpecified 在基类型中设置为始终为 true,在派生类型中始终为 false。实际的布尔值 - 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. The XmlSerializer, instead of inspecting the type itself for those attributes, will just walk through the list of override attributes provided to its constructor.
您的另一个选择是使用 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.
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. (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.
在您的情况下,您将提供 XmlIgnoreAttribute 作为覆盖,但仅限于序列化派生类型时。(或其他)这仅在您直接实例化 XmlSerializer 时才有效 - 当序列化由运行时隐式完成时,它不会起作用,就像 Web 服务一样。
Cheers!
干杯!
回答by Marc Gravell
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; public bool ShouldSerialize*()
, and public bool *Specified {get;set;}
(note you should mark *Specified
with [XmlIgnore]
too...).
基本上,有一些XmlSerializer
尊重的模式;public bool ShouldSerialize*()
, 和public bool *Specified {get;set;}
(注意你也应该*Specified
用[XmlIgnore]
...标记)。
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)]
)。