从第三方DLL反序列化二进制序列化实例提供未初始化/空实例

时间:2013-01-04 07:57:49

标签: c# properties deserialization

我有一个包含来自第三方dll的类的二进制序列化实例的文件集合。我没有访问第三方源代码但我有dll。我需要将这些文件反序列化为类的实例。

我只是这样做:

Stream stream = File.Open(@"C:\my\path", FileMode.Open);
BinaryFormatter binaryFormatter = new BinaryFormatter();
ThirdPartyType o = binaryFormatter.Deserialize(stream) as ThirdPartyType;
stream.Close();

这没有错误。当我在调试模式下运行项目并在反序列化后放置一个断点时,我可以检查实例oo的所有成员都是null0,因此实例已创建,但没有成员初始化为正确的值。

我尝试反编译dll(使用.Net Reflector)并在以下位置插入断点:

protected ThirdPartyType(SerializationInfo info, StreamingContext context) {}

现在我可以检查参数info,在这里我可以看到成员m_typesm_members& m_data设置为我期望从序列化文件中获取的正确值。但是,由于某种原因,构造函数不会使用它并正确初始化实例。我只能看到这个构造函数头,反编译器不会显示它的代码。

为了控制初始化,我创建了一个类的本地子类:

[Serializable]
public class FakeThirdPartyType : ThirdPartyType
{
    protected FakeThirdPartyType(SerializationInfo info, StreamingContext context) : base(info, context)
    {
        int width = info.GetInt32("clientWidth");
        this.ClientWidth = width;
        //Many other properties as well...
    }
}

然后我将BinaryFormatter绑定到SerializationBinder,当{1}}被要求时,FakeThirdPartyType会返回ThirdPartyType(以及其他任何调用的正确类型)。现在,当我运行它时,我会进入我的反序列化构造函数。但在这里我有一个非常奇怪的问题。我可以看到width被分配了正确的值(!=0),但在下一行this.ClientWidth仍然是0之后。结果与:

相同
base.GetType().GetProperty("ClientWidth").SetValue(this, width, null);

可能有什么我做错了吗?我遇到的问题可能是由交叉装配反序列化引起的吗?错误可能在于我无法访问的第三方代码吗?似乎属性的setter不起作用(至少不会影响getter返回的相同变量)。

在调试过程中,我可以检查ThirdPartyType类型并看到它有私有字段_clientWidth,但我找不到任何直接设置的方法。

1 个答案:

答案 0 :(得分:0)

在一些反编译后,类的属性都如下所示:

    public int Property
    {
        [MethodImpl(MethodImplOptions.NoInlining)]
        get
        {
            return 0;
        }
        [MethodImpl(MethodImplOptions.NoInlining)]
        set
        {
        }
    }

    public Object Property2
    {
        [MethodImpl(MethodImplOptions.NoInlining)]
        get
        {
            return null;
        }
    }

这当然是导致反序列化后所有值为null和0的原因。为什么这些属性是这样的,这是一个谜。但这不属于这个问题的范围。