XML Serialize dynamic object

19,265
[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>
Share:
19,265
Olav Haugen
Author by

Olav Haugen

Coding C# for food. Nerd is my middle name. Twitter Updates Blog

Updated on June 01, 2022

Comments

  • Olav Haugen
    Olav Haugen about 2 years

    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?

  • Olav Haugen
    Olav Haugen almost 13 years
    It does indeed serialize without throwing exceptions, but not into what I expected (see example XML in question). I get nodes of the type KeyValueOfstringanyType.