Introduction
Recently, I have started to look into implementing Inversion of control (IoC) using the Unity framework from Microsoft's patterns and practices. The general IoC is by arranging implementation of classes that is implemented indirectly by using interfaces. This means that if you choose to apply your setting to the registered interface and want to save this for later, it is very practical to be able to serialize the interface. However, this is not implemented out of the box by the .NET Framework.
There is one thing that is a big advantage, and that is that the interfaces are implemented by known types, so all we need to do is grab the types and values that are implemented by the class and save these to a file.
The implementation with its limitations is described in this answer given here and this tip implements the serializer given and adds the deserializer into a project so that it is easily accessible to people. Also, fixed potential memory leak, see the comment below.
Code
The serializer is implemented as was given in the answer as follows:
public static XElement Serialize(object ImplementedInterface)
{
Type ObjectType = ImplementedInterface.GetType();
Type[] ImplementedTypes = ObjectType.GetProperties()
.Where(p => p.PropertyType.IsInterface)
.Select(p => p.GetValue(ImplementedInterface, null).GetType())
.ToArray();
DataContractSerializer serializer = new DataContractSerializer(ObjectType, ImplementedTypes);
using (StringWriter sw = new StringWriter())
{
using (XmlTextWriter xw = new XmlTextWriter(sw))
{
serializer.WriteObject(xw, ImplementedInterface);
return XElement.Parse(sw.ToString());
}
}
}
and the Deserializer is constructed using the same method:
public static T Deserialize<T>(XElement File, object implementedInterface)
{
Type ObjectType = implementedInterface.GetType();
Type[] ImplementedTypes = ObjectType.GetProperties()
.Where(p => p.PropertyType.IsInterface)
.Select(p => p.GetValue(implementedInterface, null).GetType())
.ToArray();
DataContractSerializer serializer = new DataContractSerializer(ObjectType, ImplementedTypes);
using (StringReader sr = new StringReader(File.ToString()))
{
using (XmlTextReader xr = new XmlTextReader(sr))
{
return (T)serializer.ReadObject(xr);
}
}
}
There are some shortcomings of this implementation, and this is if the implementation is of the type IList<IMyItems>
or any other implementations where there are nested dependencies of other interface types. These issues can be solved by using reflection.
Usage
The serialization and deserialization can be implemented as:
ISettings MySettings;
MySettings = new Settings() { Name = "MyFile", ID = 2 };
XElement XMLFile = InterfaceSerializer.Serialize(MySettings);
MySettings.ID = 1;
MySettings.Name = "OldFile";
ISettings OldSettings = InterfaceSerializer.Deserialize<ISettings>(XMLFile,MySettings);
Of all the possible ways to solve the serialization and deserialization of implemented interfaces, I found this method to be the easiest to use in my project.