C# 将对象序列化为XmlDocument

C# 将对象序列化为XmlDocument,c#,xml-serialization,xmldocument,C#,Xml Serialization,Xmldocument,为了在SoapException.Detail中返回asmx web服务的有用信息,我从WCF中汲取了一个想法,创建了一个fault类来包含所述有用信息。然后,该故障对象被序列化为抛出的SoapException所需的XmlNode 我想知道我是否有最好的代码来创建XmlDocument——以下是我的看法: var xmlDocument = new XmlDocument(); var serializer = new XmlSerializer(typeof(T)); using (var

为了在
SoapException.Detail
中返回asmx web服务的有用信息,我从WCF中汲取了一个想法,创建了一个fault类来包含所述有用信息。然后,该故障对象被序列化为抛出的SoapException所需的
XmlNode

我想知道我是否有最好的代码来创建
XmlDocument
——以下是我的看法:

var xmlDocument = new XmlDocument();
var serializer = new XmlSerializer(typeof(T));
using (var stream = new MemoryStream())
{
    serializer.Serialize(stream, theObjectContainingUsefulInformation);
    stream.Flush();
    stream.Seek(0, SeekOrigin.Begin);

    xmlDocument.Load(stream);
}
有更好的方法吗

更新:我实际上完成了以下操作,因为除非将XML包装在
XML元素中,否则客户端会出现
SoapHeaderException

var serialiseToDocument = new XmlDocument();
var serializer = new XmlSerializer(typeof(T));
using (var stream = new MemoryStream())
{
    serializer.Serialize(stream, e.ExceptionContext);
    stream.Flush();
    stream.Seek(0, SeekOrigin.Begin);

    serialiseToDocument.Load(stream);
}

// Remove the xml declaration
serialiseToDocument.RemoveChild(serialiseToDocument.FirstChild);

// Memorise the node we want
var serialisedNode = serialiseToDocument.FirstChild;

// and wrap it in a <detail> element
var rootNode = serialiseToDocument.CreateNode(XmlNodeType.Element, "detail", "");
rootNode.AppendChild(serialisedNode);
var serialiseToDocument=new XmlDocument();
var serializer=newxmlserializer(typeof(T));
使用(var stream=new MemoryStream())
{
serializer.Serialize(流,例如ExceptionContext);
stream.Flush();
stream.Seek(0,SeekOrigin.Begin);
serialiseToDocument.Load(流);
}
//删除xml声明
serialiseToDocument.RemoveChild(serialiseToDocument.FirstChild);
//记住我们想要的节点
var serialisedNode=serialiseToDocument.FirstChild;
//并将其包装在一个元素中
var rootNode=serialiseToDocument.CreateNode(XmlNodeType.Element,“detail”,“detail”);
AppendChild(serialisedNode);
更新2:给约翰·桑德斯一个极好的答案,我现在开始使用以下方法:

private static void SerialiseFaultDetail()
{
    var fault = new ServiceFault
                    {
                        Message = "Exception occurred",
                        ErrorCode = 1010
                    };

    // Serialise to the XML document
    var detailDocument = new XmlDocument();
    var nav = detailDocument.CreateNavigator();

    if (nav != null)
    {
        using (XmlWriter writer = nav.AppendChild())
        {
            var ser = new XmlSerializer(fault.GetType());
            ser.Serialize(writer, fault);
        }
    }

    // Memorise and remove the element we want
    XmlNode infoNode = detailDocument.FirstChild;
    detailDocument.RemoveChild(infoNode);

    // Move into a root <detail> element
    var rootNode = detailDocument.AppendChild(detailDocument.CreateNode(XmlNodeType.Element, "detail", ""));
    rootNode.AppendChild(infoNode);

    Console.WriteLine(detailDocument.OuterXml);
    Console.ReadKey();
}
private static void SerialiseFaultDetail()
{
var故障=新服务故障
{
Message=“发生异常”,
错误代码=1010
};
//序列化到XML文档
var detailDocument=新的XmlDocument();
var nav=detailDocument.CreateNavigator();
如果(导航!=null)
{
使用(XmlWriter=nav.AppendChild())
{
var ser=新的XmlSerializer(fault.GetType());
序列序列化(写入程序、错误);
}
}
//记住并删除我们想要的元素
XmlNode infoNode=detailDocument.FirstChild;
detailDocument.RemoveChild(infoNode);
//移动到根元素中
var rootNode=detailDocument.AppendChild(detailDocument.CreateNode(XmlNodeType.Element,“detail”和“”);
AppendChild(infoNode);
WriteLine(detailDocument.OuterXml);
Console.ReadKey();
}

编辑:在细节元素内部创建输出

public class MyFault
{
    public int ErrorCode { get; set; }
    public string ErrorMessage { get; set; }
}

public static XmlDocument SerializeFault()
{
    var fault = new MyFault
                    {
                        ErrorCode = 1,
                        ErrorMessage = "This is an error"
                    };

    var faultDocument = new XmlDocument();
    var nav = faultDocument.CreateNavigator();
    using (var writer = nav.AppendChild())
    {
        var ser = new XmlSerializer(fault.GetType());
        ser.Serialize(writer, fault);
    }

    var detailDocument = new XmlDocument();
    var detailElement = detailDocument.CreateElement(
        "exc", 
        SoapException.DetailElementName.Name,
        SoapException.DetailElementName.Namespace);
    detailDocument.AppendChild(detailElement);
    detailElement.AppendChild(
        detailDocument.ImportNode(
            faultDocument.DocumentElement, true));
    return detailDocument;
}

+1是一个非常简洁的解决方案。但是,考虑到我需要将序列化对象的XML封装在根“”元素中,最好的方法是什么?我尝试创建一个节点,然后使用新节点的导航器,但是得到了一个InvalidOperationException,它是“在使用ConformanceLevel.Fragment创建的写入程序上无法调用WriteStartDocument”。啊,现在我明白了。为AppendChild调用使用ImportNode的返回值是我丢失的链中的链接。我必须说,我真的很讨厌.net中这些凌乱的XML类。谢谢你的帮助。总的来说,我觉得它不错,不过我想在这种情况下我会使用强类型对象而不是变量。另外,我也不知道stream.Seak(0,SeekOrigin.Begin)是否真的是必要的。我更新了详细元素的post代码。