C# 何时使用ShouldSerializeXXX与XmlIgnoreAttribute进行XML序列化
我寻找了一些在xml序列化和反序列化期间忽略类属性的示例。我发现了三种不同的方法,但不知道应该在什么时候使用。我特别感兴趣的是,哪一个更好C# 何时使用ShouldSerializeXXX与XmlIgnoreAttribute进行XML序列化,c#,c#-4.0,serialization,xml-serialization,xmlserializer,C#,C# 4.0,Serialization,Xml Serialization,Xmlserializer,我寻找了一些在xml序列化和反序列化期间忽略类属性的示例。我发现了三种不同的方法,但不知道应该在什么时候使用。我特别感兴趣的是,哪一个更好 属性 公共类项目 { [XmlIgnore] 公共字符串名称{get;set;} } 以开头的方法应序列化… 公共类项目 { 公共字符串名称{get;set;} 公共bool应序列化名称() { 返回false; } } 属性 公共类项目 { [非串行化] 公共字符串名称{get;set;} } 如果对和上的XmlIgnoreAttribtue和Non
公共类项目
{
[XmlIgnore]
公共字符串名称{get;set;}
}
开头的方法应序列化…
公共类项目
{
公共字符串名称{get;set;}
公共bool应序列化名称()
{
返回false;
}
}
公共类项目
{
[非串行化]
公共字符串名称{get;set;}
}
如果对和上的
XmlIgnoreAttribtue
和NonSerializedAttribute
之间的差异有一些解释,我无法找到有关何时使用XmlIgnoreAttribtue
以及何时应序列化模式的信息。我用XmlSerializer尝试了这两种方法,两种方法都能如期工作。1和2之间的基本区别在于它们生成的结果不同。如果希望从类型的架构中排除成员,请使用。如果希望有条件地包括成员,请使用或。(最后,如中所述,XmlSerializer
忽略了选项3中的内容)
要查看#1和#2之间的差异,可以使用为类型生成模式。为版本#1生成以下架构,并完全省略名称
成员:
<xs:complexType name="Item" />
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="1" name="Name" type="xs:string" />
</xs:sequence>
出现这种差异是因为XmlSerializer
和xsd.exe
都执行静态类型分析,而不是动态代码分析。这两个工具都无法确定案例2中的Name
属性将始终被跳过,因为这两个工具都没有尝试对ShouldSerializeName()
的源代码进行反编译,以证明它总是返回false
。因此,Name
将出现在版本2的模式中,尽管在实践中从未出现过。如果随后创建一个web服务并使用发布模式(或只是手动使其可用),将为这两种类型生成不同的客户机——一个没有名称
成员,另一个有
当所讨论的属性是不可为null的值类型时,可能会产生额外的复杂性。考虑以下三个版本的<代码>项目< /代码>。首先,具有无条件包含值属性的版本:
public class Item
{
public int Id { get; set; }
}
public class Item
{
[XmlIgnore]
public int Id { get; set; }
}
<xs:complexType name="Item" />
public class Item
{
public int Id { get; set; }
public bool ShouldSerializeId()
{
return false;
}
}
生成始终存在Id
的以下架构:
<xs:complexType name="Item">
<xs:sequence>
<xs:element minOccurs="1" maxOccurs="1" name="Id" type="xs:int" />
</xs:sequence>
</xs:complexType>
生成完全忽略Id
属性的以下架构:
public class Item
{
public int Id { get; set; }
}
public class Item
{
[XmlIgnore]
public int Id { get; set; }
}
<xs:complexType name="Item" />
public class Item
{
public int Id { get; set; }
public bool ShouldSerializeId()
{
return false;
}
}
生成以下架构,其中Id
仅有条件地存在:
<xs:complexType name="Item">
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="1" name="Id" type="xs:int" />
</xs:sequence>
</xs:complexType>
有关绑定到条件序列化值成员的更多详细信息,请参阅和
这是主要区别,但也有次要区别,可能会影响您的选择:
[XmlIgnore]
不能在派生类中被重写,但是ShouldSerializeXXX()
标记为虚拟时可以被重写;有关示例,请参见
- 如果一个成员不能被
XmlSerializer
序列化,例如,因为它引用了一个类型,那么用[XmlIgnore]
标记该成员将允许序列化包含的类型,而添加ShouldSerializeXXX(){return false;}
将不允许序列化包含的类型,因为如前所述,XmlSerializer只执行静态类型分析。例如:
public class RootObject
{
// This member will prevent RootObject from being serialized by XmlSerializer despite the fact that the ShouldSerialize method always returns false.
// To make RootObject serialize successfully, [XmlIgnore] must be added.
public NoDefaultConstructor NoDefaultConstructor { get; set; }
public bool ShouldSerializeNoDefaultConstructor() { return false; }
}
public class NoDefaultConstructor
{
public string Name { get; set; }
public NoDefaultConstructor(string name) { this.Name = name; }
}
无法由XmlSerializer
序列化
[XmlIgnore]
特定于XmlSerializer
,但ShouldSerializeXXX()
被其他序列化程序使用,包括和
- 如注释中所述,在Visual Studio中重命名有条件序列化的属性不会自动重命名相应的
ShouldSerializeXXX()
方法名,从而导致潜在的维护问题
如果它们都符合您的标准,请选择您喜欢的。PSShouldSerializeXXX
版本是个糟糕的主意,不要用那个@DavidG:Con你可以争论为什么使用ShouldSerializeXXX
是个糟糕的主意。你会用所有这些额外的方法污染你的模型,而属性不会。不使用ShouldSerializeXXX的另一个原因是在实现了所有这些之后,当后来有人进来需要更改字段名称时会发生什么情况。该任务现在在开发人员不知道的情况下中断了序列化。XmlSerializer似乎没有像JSON.net那样的ContractResolver,这使得ShouldSerialize成为动态包含/排除成员的唯一方法。我们使用T4模板生成ShouldSerializeXxxx函数。我们有这么多属性,生成的文件有10000行代码。非常感谢您的详细解释。这给了我一个完美的决策指导。伟大的