反序列化IEnumerable<>使用BinaryFormatter - 错误/奇怪的行为

时间:2013-12-31 13:11:27

标签: c# .net serialization ienumerable binaryformatter

我有一个程序集可以保存并加载(或尝试)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;
}

谢谢你的时间!

0 个答案:

没有答案