XML序列化动态对象 [英] XML Serialize dynamic object

查看:350
本文介绍了XML序列化动态对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要构建一套动态创建的XML节点的对象上的格式如下:

 <根和GT;
    <名称>我的姓名和LT; /名称>
    < D​​ynamicValues​​>
        < D​​ynamicValue1>价值1< / DynamicValue1>
        < D​​ynamicValue2>价值2'; / DynamicValue2>
    < / DynamicValues​​>
< /根>
 

DynamicValues​​ -tag都事先不知道该节点的名称。我最初的想法是,这个使用 Expando的对象,比如应该是可能的:

  [DataContract]
公共类根
{
    [数据成员]
    公共字符串名称{;组; }

    [数据成员]
    公共动态DynamicValues​​ {获得;组; }
}
 

通过与值对其进行初始化:

  VAR根=新根
                    {
                        NAME =我的名字,
                        DynamicValues​​ =新ExpandoObject()
                    };

root.DynamicValues​​.DynamicValue1 =值1;
root.DynamicValues​​.DynamicValue2 =值2;
 

然后的XML序列化:

 字符串的xmlString;

无功序列化=新的DataContractSerializer(root.GetType());
使用(VAR的支持=新的StringWriter())
使用(VAR作家=新的XmlTextWriter(背衬))
{
    serializer.WriteObject(作家,根);
    的xmlString = backing.ToString();
}
 

然而,当我运行它,我得到一个SerializationException说:

  

类型System.Dynamic.ExpandoObject'数据合同名称   ArrayOfKeyValueOfstringanyType:HTTP://schemas.microsoft.com/2003/10/Serialization/Arrays   预计不会。考虑使用DataContractResolver或添加任何   不已知类型静态已知类型的列表 - 例如,   通过使用KnownTypeAttribute属性或通过将其添加到   已知类型传递给DataContractSerializer的列表中。

任何想法我如何能做到这一点?

解决方案

  [Serializable接口]
公共类DynamicSerializable:DynamicObject,ISerializable的
{
    私人只读字典<字符串,对象>词典=新词典<字符串,对象>();

    公众覆盖布尔TrySetMember(SetMemberBinder粘结剂,对象值)
    {
        词典[binder.Name] =值;

        返回true;
    }

    公共无效GetObjectData使用(SerializationInfo中的信息,的StreamingContext上下文)
    {
        的foreach(在字典VAR KVP)
        {
            info.AddValue(kvp.Key,kvp.Value);
        }
    }
}

[KnownType(typeof运算(DynamicSerializable))]
[DataContract]
公共类根
{
    [数据成员]
    公共字符串名称{;组; }

    [数据成员]
    公共动态DynamicValues​​ {获得;组; }
}
 

输出:

 < Program.Root的xmlns:I =htt​​p://www.w3.org/2001/XMLSchema-instance的xmlns =HTTP://
schemas.datacontract.org/2004/07/">
  < D​​ynamicValues​​我:TYPE =Program.DynamicSerializable>
    < D​​ynamicValue1的xmlns:d3p1 =htt​​p://www.w3.org/2001/XMLSchema我:TYPE =d3p1:ST
环的xmlns =>价值1< / DynamicValue1>
    < D​​ynamicValue2的xmlns:d3p1 =htt​​p://www.w3.org/2001/XMLSchema我:TYPE =d3p1:ST
环的xmlns =>值2'; / DynamicValue2>
  < / DynamicValues​​>
  <名称>我的姓名和LT; /名称>
< /Program.Root>
 

I need to construct a set of dynamically created XML nodes from objects on the following format:

<Root>
    <Name>My Name</Name>
    <DynamicValues>
        <DynamicValue1>Value 1</DynamicValue1>
        <DynamicValue2>Value 2</DynamicValue2>
    </DynamicValues>
</Root>

The name of the nodes within the DynamicValues-tag are not known in advance. My initial thought was that this should be possible using an Expando Object, e.g:

[DataContract]
public class Root
{
    [DataMember]
    public string Name { get; set; }

    [DataMember]
    public dynamic DynamicValues { get; set; }
}

by initializing it with the values:

var root = new Root
                    {
                        Name = "My Name",
                        DynamicValues = new ExpandoObject()
                    };

root.DynamicValues.DynamicValue1 = "Value 1";
root.DynamicValues.DynamicValue2 = "Value 2";

and then Xml-serialize it:

string xmlString;

var serializer = new DataContractSerializer(root.GetType());
using (var backing = new StringWriter())
using (var writer = new XmlTextWriter(backing))
{
    serializer.WriteObject(writer, root);
    xmlString = backing.ToString();
}

However, when I run this, I get an SerializationException saying:

"Type 'System.Dynamic.ExpandoObject' with data contract name 'ArrayOfKeyValueOfstringanyType:http://schemas.microsoft.com/2003/10/Serialization/Arrays' is not expected. Consider using a DataContractResolver or add any types not known statically to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding them to the list of known types passed to DataContractSerializer."

Any ideas how I can achieve this?

解决方案

[Serializable]
public class DynamicSerializable : DynamicObject, ISerializable
{
    private readonly Dictionary<string, object> dictionary = new Dictionary<string, object>();

    public override bool TrySetMember(SetMemberBinder binder, object value)
    {
        dictionary[binder.Name] = value;

        return true;
    }

    public void GetObjectData(SerializationInfo info, StreamingContext context)
    {
        foreach (var kvp in dictionary)
        {
            info.AddValue(kvp.Key, kvp.Value);
        }
    }
}

[KnownType(typeof(DynamicSerializable))]
[DataContract]
public class Root
{
    [DataMember]
    public string Name { get; set; }

    [DataMember]
    public dynamic DynamicValues { get; set; }
}

Output:

<Program.Root xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://
schemas.datacontract.org/2004/07/">
  <DynamicValues i:type="Program.DynamicSerializable">
    <DynamicValue1 xmlns:d3p1="http://www.w3.org/2001/XMLSchema" i:type="d3p1:st
ring" xmlns="">Value 1</DynamicValue1>
    <DynamicValue2 xmlns:d3p1="http://www.w3.org/2001/XMLSchema" i:type="d3p1:st
ring" xmlns="">Value 2</DynamicValue2>
  </DynamicValues>
  <Name>My Name</Name>
</Program.Root>

这篇关于XML序列化动态对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆