序列化包含可变内容的标准xml信封

时间:2014-11-21 15:05:25

标签: c# xml serialization xml-serialization

我想创建一个可序列化的类来表示可以包含任意消息内容的xml信封。示例xml(简化)如下:

<?xml version="1.0" encoding="utf-8"?>
<Envelope>
    <MessageA>
        <Url></Url>
    </MessageA>
</Envelope>

<?xml version="1.0" encoding="utf-8"?>
<Envelope>
    <MessageB>
        <Value></Value>
    </MessageB>
</Envelope>

我的想法是使用通用的信封类来处理这个问题:

[Serializable]
[XmlRoot(ElementName="Envelope")]
public class Envelope<TContent> where TContent : new()
{
    public Envelope()
    {
        Content = new TContent();
    }
    public TContent Content { get; set; }
}

[Serializable]
public class MessageA
{
    public string Url { get; set; }
}

[Serializable]
public class MessageB
{
    public string Value { get; set; }
}

这些可以序列化:

var envelope = new Envelope<MessageA>();
envelope.Content.Url = "http://www.contoso.com";
string xml = envelope.ToXml();

但是,我得到以下内容,而不是我想要的xml消息(上面的示例)。如何更改类或序列化过程以将Content元素重命名为Message本身的名称?

<?xml version="1.0" encoding="utf-8"?>
<Envelope>
    <Content>
        <Url>http://www.contoso.com</Url>
    </Content>
</Envelope>

1 个答案:

答案 0 :(得分:0)

发现XmlAttributeOverrides类有针对此问题的解决方案。将以下方法添加到Envelope类会导致ToXml()扩展方法根据需要序列化对象。

public string ToXml()
{
    return ToXml(typeof(TContent).Name);
}

public string ToXml(string contentElementName)
{
    XmlElementAttribute element = new XmlElementAttribute(contentElementName, typeof(TContent));
    XmlAttributes attributes = new XmlAttributes();
    attributes.XmlElements.Add(element);
    XmlAttributeOverrides overrides = new XmlAttributeOverrides();
    overrides.Add(typeof(Envelope<TContent>), "Content", attributes);
    return ToXml(this, overrides);
}

public string ToXml(Envelope<TContent> value, XmlAttributeOverrides overrides) 
{
    using (var sw = new Utf8StringWriter())
    {
        var settings = new XmlWriterSettings
        {
            OmitXmlDeclaration = omitXmlDeclaration,
            Indent = true
        };
        XmlSerializer xs = new XmlSerializer(typeof(Envelope<TContent>), overrides);
        using (XmlWriter writer = XmlWriter.Create(sw, settings))
        {
            xs.Serialize(writer, value);
        }
        return sw.ToString();
    }
}