I realize this question is a bit old but I didn't really like the other solutions I found because they format the xml in a different way than I wanted. So I did it this way.
I made a custom dynamic type based on the dictionary keys, create an instance of this new type, then serialize that object.
public void Serialize(string OutPath, Dictionary<string, object> Input) {
//Define stuff
AssemblyName assName = new AssemblyName("CustomType");
AssemblyBuilder assBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assName, AssemblyBuilderAccess.RunAndSave);
ModuleBuilder modBuilder = assBuilder.DefineDynamicModule(assName.Name);
TypeBuilder typBuilder = modBuilder.DefineType("NewType", TypeAttributes.Public);
//Add all the keys as fields
foreach (string Key in Input.Keys) {
typBuilder.DefineField(Key, Input[Key].GetType(), FieldAttributes.Public);
}
//Make the new type
Type newType = typBuilder.CreateType();
//make instance
object newInstance = Activator.CreateInstance(newType);
//set Values
foreach (string Key in Input.Keys) {
newInstance.GetType().GetField(Key).SetValue(newInstance, Input[Key]);
}
//serialize XML
XmlSerializer xs = new XmlSerializer(newType);
TextWriter tw = new StreamWriter(OutPath);
xs.Serialize(tw, newInstance);
tw.Flush();
tw.Close();
}
If you want to include a dictionary with primitive fields from another type, you can just include the object in the parameters to pass the values and add some stuff like this to the proper locations:
//This part adds the fields to the custom type, include near where the dictionary keys are being added as fields
foreach (FieldInfo FI in InputObject.GetType().GetFields()) {
if (FI.FieldType.IsPrimitive || FI.FieldType == typeof(string)) {
FieldInfo fi = newInstance.GetType().GetField(FI.Name);
fi.SetValue(newInstance, FI.GetValue(InputObject));
}
}
//This part adds the values to the object, include near where the values are being set
foreach (FieldInfo FI in InputObject.GetType().GetFields()) {
if (FI.FieldType.IsPrimitive || FI.FieldType == typeof(string)) {
FieldBuilder fieBuilder = typBuilder.DefineField(FI.Name, FI.FieldType, FieldAttributes.Public);
}
}
This code:
//build dictionary
Dictionary<string, object> Input = new Dictionary<string, object>();
Input.Add("Value1", "One");
Input.Add("Value2", "Two");
Input.Add("Value3", 3);
Input.Add("Date", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
//Serialize!
Serialize(FilePath, Input);
Builds an xml output like this:
<?xml version="1.0" encoding="utf-8" ?>
- <NewType xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Value1>One</Value1>
<Value2>Two</Value2>
<Value3>3</Value3>
<Date>2014-08-28 18:03:58</Date>
</NewType>
Then you can read in/deserialize the xml like this:
public Dictionary<string, object> Deserialize(string OutPath) {
Dictionary<string, object> Output = new Dictionary<string, object>();
//create the xmlDocument
XmlDocument xd = new XmlDocument();
xd.Load(XmlReader.Create(OutPath));
//Scan all the nodes in the main doc and add them to the dictionary
//you can recursively check child nodes if your document requires.
foreach (XmlNode node in xd.DocumentElement) {
Output.Add(node.Name, node.InnerText);
}
return Output;
}