簡體   English   中英

C# XmlSerializer 用不同的命名空間序列化相同的 class

[英]C# XmlSerializer Serialize the same class with different namespaces

假設我有一個 class:

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 使用我在運行時選擇的命名空間?

是的; 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);
    }

然而!!!

執行此操作時,它每次都會在 memory 中生成一個附加程序集; 必須緩存並重用序列化程序實例 - 通常通過並發字典或類似的方式。 例如:

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);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM