I'd rather extract my custom types all at once and use it during serialization/deserialization. After reading this post, it took me a while to understand where to inject this list of types to be useful for serializer object. The answer was quite easy: this list is to be used as one of the input arguments of constructor of serializer object.
1- I'm using two static generic methods for serialization and deserialization, this may be more or less the way others also do the job, or at least it is very clear for making comparison with your code:
public static byte[] Serialize<T>(T obj)
{
var serializer = new DataContractSerializer(typeof(T), MyGlobalObject.ResolveKnownTypes());
var stream = new MemoryStream();
using (var writer =
XmlDictionaryWriter.CreateBinaryWriter(stream))
{
serializer.WriteObject(writer, obj);
}
return stream.ToArray();
}
public static T Deserialize<T>(byte[] data)
{
var serializer = new DataContractSerializer(typeof(T), MyGlobalObject.ResolveKnownTypes());
using (var stream = new MemoryStream(data))
using (var reader =
XmlDictionaryReader.CreateBinaryReader(
stream, XmlDictionaryReaderQuotas.Max))
{
return (T)serializer.ReadObject(reader);
}
}
2- Please pay attention to constructor of DataContractSerializer. We have a second argument there, which is the entry point for injecting your known types to serializer object.
3- I'm using a static method for extracting all of my own defined types from my own assemblies. your code for this static method may look like this:
private static Type[] KnownTypes { get; set; }
public static Type[] ResolveKnownTypes()
{
if (MyGlobalObject.KnownTypes == null)
{
List<Type> t = new List<Type>();
List<AssemblyName> c = System.Reflection.Assembly.GetEntryAssembly().GetReferencedAssemblies().Where(b => b.Name == "DeveloperCode" | b.Name == "Library").ToList();
foreach (AssemblyName n in c)
{
System.Reflection.Assembly a = System.Reflection.Assembly.Load(n);
t.AddRange(a.GetTypes().ToList());
}
MyGlobalObject.KnownTypes = t.ToArray();
}
return IOChannel.KnownTypes;
}
Since I was not involved in WCF (I only needed a binary serialization for file operation), my solution may not exactly address the WCF architecture, but there must be access to constructor of serializer object from somewhere.
return Assembly.GetExecutingAssembly().GetTypes().Where(_ => _.IsSubclassOf(typeof(TaskBase))).ToArray();
– Abydos