C# XmlSerializer 用不同的命名空间序列化同一个类
Posted
技术标签:
【中文标题】C# XmlSerializer 用不同的命名空间序列化同一个类【英文标题】:C# XmlSerializer Serialize the same class with different namespaces 【发布时间】:2021-07-04 09:07:43 【问题描述】:假设我有一堂课:
using System.Xml;
using System.Xml.Serialization;
class Foo
[XmlElement(ElementName="Bar")]
public string Bar get; set;
现在我想序列化它。但。我想指定不同的命名空间, 有一次我希望我的 XML 看起来像这样:
<Foo xmlns:v1="http://site1">
<v1:Bar />
</Foo>
另一方面,像这样:
<Foo xmlns:v2="http://site2">
<v2:Bar />
</Foo>
我知道我需要在 XmlElement 属性中指定命名空间,但这正是我想要避免的。 当然,我可以制作 2 个不同的类,除了字段属性之外它们是相同的,但这在某种程度上感觉是错误的。 有什么办法可以强制 XmlSerializer 使用我在运行时选择的命名空间?
【问题讨论】:
【参考方案1】:是的; XmlAttributeOverrides
:
static void Main()
var obj = new Foo Bar = "abc" ;
GetSerializer("http://site1").Serialize(Console.Out, obj);
Console.WriteLine();
GetSerializer("http://site2").Serialize(Console.Out, obj);
static XmlSerializer GetSerializer(string barNamespace)
var ao = new XmlAttributeOverrides();
var a = new XmlAttributes();
a.XmlElements.Add(new XmlElementAttribute Namespace = barNamespace );
ao.Add(typeof(Foo), nameof(Foo.Bar), a);
return new XmlSerializer(typeof(Foo), ao);
但是!!!
当你这样做时,它每次都会在内存中生成一个额外的程序集;您必须缓存并重复使用序列化程序实例 - 通常通过并发字典或类似方式。例如:
private static readonly ConcurrentDictionary<string, XmlSerializer>
s_serializersByNamespace = new();
static XmlSerializer GetSerializer(string barNamespace)
if (!s_serializersByNamespace.TryGetValue(barNamespace, out var serializer))
lock (s_serializersByNamespace)
// double-checked, avoid dups
if (!s_serializersByNamespace.TryGetValue(barNamespace, out serializer))
var ao = new XmlAttributeOverrides();
var a = new XmlAttributes();
a.XmlElements.Add(new XmlElementAttribute Namespace = barNamespace );
ao.Add(typeof(Foo), nameof(Foo.Bar), a);
serializer = new XmlSerializer(typeof(Foo), ao);
s_serializersByNamespace[barNamespace] = serializer;
return serializer;
注意:如果你也想要特定的xmlns
控件,那就是XmlSerializerNamespaces
:
var obj = new Foo Bar = "abc" ;
var ns = new XmlSerializerNamespaces();
ns.Add("v1", "http://site1");
GetSerializer("http://site1").Serialize(Console.Out, obj, ns);
Console.WriteLine();
ns = new XmlSerializerNamespaces();
ns.Add("v2", "http://site2");
GetSerializer("http://site2").Serialize(Console.Out, obj, ns);
【讨论】:
我想我必须为我的每个类可序列化属性一个一个地添加一个覆盖? @cicatrix 是的,虽然我相信相同的属性 instances 如果它们相似的话可以被重用;把它想象成常规属性:你需要单独应用它们每个成员以上是关于C# XmlSerializer 用不同的命名空间序列化同一个类的主要内容,如果未能解决你的问题,请参考以下文章
C# XMLSerializer 将错误的类型反序列化为 List
C#语言中的XmlSerializer类的Serialize(Stream,Object)方法举例详解
使用不带属性的 DataContractSerializer 或 XmlSerializer 删除所有命名空间
我可以让 XmlSerializer 在反序列化时忽略命名空间吗?