XML Serialize动态对象

时间:2011-09-21 14:48:02

标签: c# .net xml serialization dynamic

我需要按照以下格式从对象构造一组动态创建的XML节点:

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

预先不知道DynamicValues - 标记内的节点名称。我最初的想法是,这应该可以使用Expando Object,例如:

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

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

通过使用值

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

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

然后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();
}

但是,当我运行它时,我得到一个SerializationException:

  

“输入带有数据合约名称的'System.Dynamic.ExpandoObject'   'ArrayOfKeyValueOfstringanyType:http://schemas.microsoft.com/2003/10/Serialization/Arrays'   不是预期的。考虑使用DataContractResolver或添加任何   静态地知道已知类型列表的类型 - 例如,   通过使用KnownTypeAttribute属性或将它们添加到   传递给DataContractSerializer的已知类型列表。“

我是如何实现这一目标的?

2 个答案:

答案 0 :(得分:25)

[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; }
}

输出:

<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>

答案 1 :(得分:0)

在vb.net中尝试过此操作但未获得所需的输出。 需要帮助。

_ 公共类DynamicSerializable     继承System.Dynamic.DynamicObject     实现ISerializable

Private ReadOnly dict As New Dictionary(Of String, Object)

Public Overrides Function TrySetMember(binder As SetMemberBinder, value As Object) As Boolean
    If Not dict.ContainsKey(binder.Name) Then
        dict.Add(binder.Name, value)
    Else
        dict(binder.Name) = value
    End If
    Return True
End Function

Public Overrides Function TryGetMember(binder As GetMemberBinder, ByRef result As Object) As Boolean
    Return dict.TryGetValue(binder.Name, result)
End Function

Public Sub GetObjectData(info As SerializationInfo, context As StreamingContext) Implements ISerializable.GetObjectData
    For Each keyValPair In dict
        info.AddValue(keyValPair.Key, keyValPair.Value)
    Next
End Sub

结束班

使用的代码:

Dim root As New Root         root.name =“1”         root.DynamicValues =新的DynamicSerializable

    root.DynamicValues.DynamicValue1 = "Value1"
    root.DynamicValues.DynamicValue2 = "Value1"

    Dim serializer = New DataContractSerializer(Root.GetType)
    Dim backing As New StringWriter
    Dim writer As New XmlTextWriter(backing)
    serializer.WriteObject(writer, Root)

输出: