我宁愿一次性提取我的自定义类型并在序列化/反序列化期间使用它。读完这篇文章后,我花了一段时间才明白在哪里注入这个类型列表以对序列化器对象有用。答案很简单:这个列表将用作序列化器对象的构造函数的输入参数之一。
1-我使用两种静态通用方法进行序列化和反序列化,这可能或多或少是其他人也做这项工作的方式,或者至少与您的代码进行比较非常清楚:
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- 请注意 DataContractSerializer 的构造函数。我们在那里有第二个参数,它是将已知类型注入序列化程序对象的入口点。
3- 我使用静态方法从我自己的程序集中提取我自己定义的所有类型。此静态方法的代码可能如下所示:
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;
}
由于我没有参与 WCF(我只需要对文件操作进行二进制序列化),因此我的解决方案可能无法完全解决 WCF 架构,但必须可以从某个地方访问序列化程序对象的构造函数。