如何将动态对象序列化为XML C#

6

我有一个包含1000个object {DynamicData}object {System.Collections.Generic.List<object>},每个对象都有4个键和值以及一个内部包含2个键和值的List

我需要将这个对象序列化成XML文件,但使用普通的序列化会出现异常:The type DynamicData was not expected,我该如何序列化这个对象?

这是代码:

           //output is the name of my object
            XmlSerializer xsSubmit = new XmlSerializer(output.GetType());
            var xml = "";

            using (var sww = new StringWriter())
            {
                using (XmlWriter writers = XmlWriter.Create(sww))
                {
                    try
                    {
                        xsSubmit.Serialize(writers, output);
                    }
                    catch (Exception ex)
                    {

                        throw;
                    }
                    xml = sww.ToString(); // Your XML
                }
            }

我可以逐行逐个元素地创建XML文件,但我想要更快速、代码更少的方式。

我的对象结构如下:

output (count 1000)
 [0]
   Costumer - "Costumername"
   DT - "Date"
   Key - "Key"
   Payment - "x"
   [0]
    Adress - "x"
    Number - "1"
 [1]...
 [2]...

离题:你实际上正在处理“顾客”吗?我的意思是,肯定有一些系统中存在他们,只是我从来没有遇到过。 - oerkelens
你正在序列化的类型不清楚。它是否有[Serializable]属性?为什么使用object而不是具体类型? - JohnyL
1
XmlSerializer 不太适合你想做的事情。首先,如果将你的动态对象视为字典,则 XmlSerializer 不直接支持字典。请参见 为什么 XmlSerializer 不支持字典?如何将字典进行 XML 序列化 - dbc
1
其次,当序列化多态成员时,XmlSerializer 只会序列化已知的、在白名单中的类型 -- 例如,那些使用 [XmlInclude] 包含的类型,如 xsi:type attribute messing up C# XML deserialization 中所示。这是出于安全考虑,它可以防止构造风险类型,比如在 TypeNameHandling caution in Newtonsoft Json 中所描述的那些类型。 - dbc
1
有关可能的解决方法,请参见XML序列化和继承类型使用XmlSerializer序列化多种类型的数组 - 但您需要小心可能存在的安全隐患。 - dbc
显示剩余2条评论
1个回答

5

您可以通过使用IXmlSerializable来实现自己的序列化对象。

[Serializable]
public class ObjectSerialize :  IXmlSerializable
{
    public List<object> ObjectList { get; set; }

    public XmlSchema GetSchema()
    {
        return new XmlSchema();
    }

    public void ReadXml(XmlReader reader)
    {

    }

    public void WriteXml(XmlWriter writer)
    {
        foreach (var obj in ObjectList)
        {   
            //Provide elements for object item
            writer.WriteStartElement("Object");
            var properties = obj.GetType().GetProperties();
            foreach (var propertyInfo in properties)
            {   
                //Provide elements for per property
                writer.WriteElementString(propertyInfo.Name, propertyInfo.GetValue(obj).ToString());
            }
            writer.WriteEndElement();
        }
    }
}

用法

        var output = new List<object>
        {
            new { Sample = "Sample" }
        };
        var objectSerialize = new ObjectSerialize
        {
            ObjectList = output
        };
        XmlSerializer xsSubmit = new XmlSerializer(typeof(ObjectSerialize));
        var xml = "";

        using (var sww = new StringWriter())
        {
            using (XmlWriter writers = XmlWriter.Create(sww))
            {
                try
                {
                    xsSubmit.Serialize(writers, objectSerialize);
                }
                catch (Exception ex)
                {

                    throw;
                }
                xml = sww.ToString(); // Your XML
            }
        }

输出

<?xml version="1.0" encoding="utf-16"?>
<ObjectSerialize>
    <Object>
        <Sample>Sample</Sample>
    </Object>
</ObjectSerialize>

注意:如果您想使用相同类型(ObjectSerialize)进行反序列化,应提供ReadXml。如果您想指定模式,则还应提供GetSchema。

我无法在我的代码中创建对象,我将从内存中获取它。如何使用已经创建的对象来实现您的代码?就像这样:object output =(存储它的内存部分); - Lucio Zenir
我声明了一个名为 "Sample" 的对象作为示例。请忽略它,并将您的输出对象设置在 ObjectSerialize 实例中。 - lucky
好的,那么在序列化之后我该如何创建XML文件呢? - Lucio Zenir
它不适用于列表的次级层级,这是代码创建的xml:<ObjectSerialize> <Object> <PurchaseOrderNumber>99503</PurchaseOrderNumber> <OrderDate>1999-10-20</OrderDate> <DeliveryNotes>Please leave packages in shed by driveway.</DeliveryNotes> <Address>System.Collections.Generic.List1[Address]</Address> <Items>Item</Items> </Object> </ObjectSerialize> - Lucio Zenir
感谢您的示例@lucky!关于@lucio-zenir,对于任何想要传递具有嵌套匿名对象的匿名对象的人,这是我创建的一个示例:https://dotnetfiddle.net/WuuOWg - csteele
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接