我有一个程序集可以保存并加载(或尝试)IEnumerable<>来自/来自持久化的二进制流。
如果加载了程序集,并且在反序列化之前执行了数据的序列化,那么一切正常并且数据被反序列化并按预期加载,没有异常抛出。
但是,如果加载程序集并且在序列化发生之前请求反序列化(持久化)数据,则会生成以下错误:
The MyClass could not be transferred.
Unable to load type System.Collections.Generic.List`1[[MyClass, MyAssembly,
Version=1.2.0.0, Culture=neutral, PublicKeyToken=null]] required for deserialization.
我已经阅读了很多关于序列化ienumebles的文章,我对我所读到的内容感到有些困惑,因为许多消息来源声明它应该是不可能的,但是这段代码在过去显然有效(我已经在程序集之间移动了一些类型) (这似乎是问题的原因)但我无法将它们移回去。)
为什么只有序列化先发生才有效?如果序列化没有发生,为什么它找不到类型?为什么我没有在序列化上得到这个错误?
public void Load<T>(T instance)
{
Transfer(instance, (binaryFormatter, property, key, inst) =>
{
object value = PropertyBag.Read(key);
if(null != value)
{
using(MemoryStream memoryStream = new MemoryStream(value as byte[]))
{
property.SetValue(inst, binaryFormatter.Deserialize(memoryStream), null);
}
}
});
}
public void Save<T>(T instance)
{
Transfer(instance, (binaryFormatter, property, key, inst) =>
{
object value = property.GetValue(inst, null);
using(MemoryStream memoryStream = new MemoryStream())
{
binaryFormatter.Serialize(memoryStream, value);
PropertyBag.Write(key, memoryStream.GetBuffer());
}
});
}
internal sealed class AssemblyBinder : SerializationBinder
{
public override Type BindToType(string assemblyName, string typeName)
{
Type typeDefinition = null;
Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
try
{
string isolatedAssemblyName = assemblyName.Split(',')[0];
foreach(Assembly assembly in assemblies)
{
if(assembly.FullName.Split(',')[0] == isolatedAssemblyName)
{
typeDefinition = assembly.GetType(typeName);
break;
}
}
}
catch(System.Exception ex)
{
LogManager.Logger.Log(new LoggableException(ex));
}
return typeDefinition;
}
}
private void Transfer<T>(T instance, Action<BinaryFormatter, PropertyInfo, string, T> action)
{
Type type = typeof(T);
PropertyInfo[] properties = type.GetProperties(
GetBindingFlags());
foreach(PropertyInfo property in properties)
{
try
{
BaggableAttribute[] attributes =
property.GetCustomAttributes(typeof(BaggableAttribute), true)
as BaggableAttribute[];
if(attributes == null || attributes.Length == 0)
continue;
BinaryFormatter binaryFormatter = new BinaryFormatter();
binaryFormatter.Binder = new AssemblyBinder();
action.Invoke(binaryFormatter, property, attributes[0].Key, instance);
}
catch(Exception ex)
{
Logger.Log(new PropertyTransferException(ex, property.Name));
}
}
}
private BindingFlags GetBindingFlags()
{
return BindingFlags.Public |
BindingFlags.NonPublic |
BindingFlags.Instance;
}
谢谢你的时间!