1

我有一组文件,其中包含来自第三方 dll 的类的二进制序列化实例。我无权访问第三方源代码,但我有 dll。我需要将这些文件反序列化为类的实例。

我只是这样做:

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

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

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

protected ThirdPartyType(SerializationInfo info, StreamingContext context) {}

现在我可以检查参数info,在这里我可以看到成员m_types, m_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...
    }
}

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

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

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

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

4

1 回答 1

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 的原因。为什么这些属性是这样的,虽然是一个谜。但这不在这个问题的范围内。

于 2013-02-25T02:27:48.813 回答