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

C# 序列化包含可变内容的标准xml信封,c#,xml,serialization,xml-serialization,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"?> <En

我想创建一个可序列化的类来表示可以包含任意消息内容的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消息,而是以下内容。如何更改类或序列化过程以将内容元素重命名为消息本身的名称

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

发现XmlAttributeOverrides类对此问题有解决方案。将以下方法添加到信封类会导致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();
    }
}