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 , eg:
[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>
Tried this in vb.netbut didn't got the required output. Need help.
_ Public Class DynamicSerializable Inherits System.Dynamic.DynamicObject Implements 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
End Class
Code used :
Dim root As New Root root.name = "1" root.DynamicValues = New 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)
Output :
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.