2011-09-21 82 views
19

我需要從以下格式的對象構造一組動態創建的XML節點:XML序列化動態對象

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

DynamicValues -tag內的節點的名稱預先是未知的。我最初的想法是,這應該是可能使用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的序列化:

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的的 列表例如, 」

任何想法我怎麼能做到這一點

回答

24
[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> 
+0

它確實沒有序列化拋出異常,但不進我的預期(見問題例如XML)。我得到'KeyValueOfstringanyType'類型的節點。 –

+0

@OlavHaugen,我已經更新了我的答案。 –

+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 

末級

用於編碼:

昏暗根作爲新的根 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) 

輸出: