I am attempting to save/load a class to an xml file that contains generic types using a DataContractSerializer
. I have the save working, but have realized I can't load it because I don't have the list of knownTypes for the deserializer.
Is there a way of serializing/deserializing this class that would allow me to deserialize it without referencing any of the stored types directly?
Here is my SessionVariables
class that I am trying to save/load:
[DataContract]
public class SessionVariables
{
[DataMember]
private Dictionary<Type, ISessionVariables> _sessionVariables = new Dictionary<Type, ISessionVariables>();
private object _syncLock = new object();
public T Get<T>()
where T : ISessionVariables, new()
{
lock (_syncLock)
{
ISessionVariables vars = null;
if (_sessionVariables.TryGetValue(typeof(T), out vars))
return (T)vars;
vars = new T();
_sessionVariables.Add(typeof(T), vars);
return (T)vars;
}
}
public IList<Type> GetKnownTypes()
{
IList<Type> knownTypes = new List<Type>();
knownTypes.Add(this.GetType().GetType()); // adds System.RuntimeType
foreach (Type t in _sessionVariables.Keys)
{
if (!knownTypes.Contains(t))
knownTypes.Add(t);
}
return knownTypes;
}
}
The different modules of the application extend the ISessionVariables
interface to create their own set of session variables, like this:
[DataContract]
public class ModuleASessionVariables : ISessionVariables
{
[DataMember]
public string ModuleA_Property1{ get; set; }
[DataMember]
public string ModuleA_Property2 { get; set; }
}
[DataContract]
public class ModuleBSessionVariables : ISessionVariables
{
[DataMember]
public string ModuleB_Property1{ get; set; }
[DataMember]
public string ModuleB_Property2 { get; set; }
}
And a singleton instance of the SessionVariables
class is used to access session variables, like this:
singletonSessionVariables.Get<ModuleASessionVariables>().ModuleA_Property1
singletonSessionVariables.Get<ModuleBSessionVariables>().ModuleB_Property2
I got the save working like this:
using (FileStream writer = new FileStream(@"C:\test.txt", FileMode.Create))
{
DataContractSerializer dcs = new DataContractSerializer(typeof(SessionVariables), singletonSessionVariables.GetKnownTypes());
dcs.WriteObject(writer, singletonSessionVariables);
writer.Close();
}
However this method does not work to deserialize the class because I don't know it's known types.
Can I serialize and deserialize generic types when I don't have direct library references to any of the types used? And if so, how?
SessionVariables
object and child objects to a file without specifying the types in advance, and the types and data came out successfully. The only minor issue I had was that the _syncObject gets initialized as null when deserializing. I still need to test with moving the child objects to separate assemblies though, and making sure it can deserialize with no reference at all. – Truda