Proto使用Reflection进行序列化层次结构类型

时间:2013-01-26 19:45:31

标签: .net serialization reflection protocol-buffers protobuf-net

当尝试使用由反射加载的proto序列化程序序列化层次结构类型时,它似乎有一些奇怪的行为并且似乎无法正常工作。

这是代码:

    [ProtoContract]
    [ProtoInclude(10, typeof(Derived))]
    class Base
    {
        [ProtoMember(1)]
        public string BaseFirstProperty { get; set; }
        [ProtoMember(2)]
        public string BaseSecProperty { get; set; }
    }

    [ProtoContract]
    class Derived : Base
    {
        [ProtoMember(1)]
        public string DerivedFirstProperty { get; set; }
    }

    static void Main(string[] args)
    {
        var assembly = Assembly.LoadFile(@"c:\protobuf-net.dll");

        var derived = new Derived()
        {
            BaseFirstProperty = "BaseFirst",
            BaseSecProperty = "BaseSec",
            DerivedFirstProperty = "DerivedFirst"
        };

        var reflectionSerializer = assembly.GetType("ProtoBuf.Serializer");
        var getTypeSerializer = typeof(Serializer);

        var reflectionMethods = reflectionSerializer.GetMethods(BindingFlags.Static | BindingFlags.Public);
        var reflectionGenericMethodInfo = reflectionMethods.First<MethodInfo>(method => method.Name == "SerializeWithLengthPrefix");
        var reflectionSpecificMethodInfo = reflectionGenericMethodInfo.MakeGenericMethod(new Type[] { derived.GetType() });

        var getTypeMethods = getTypeSerializer.GetMethods(BindingFlags.Static | BindingFlags.Public);
        var getTypeGenericMethodInfo = getTypeMethods.First<MethodInfo>(method => method.Name == "SerializeWithLengthPrefix");
        var getTypeSpecificMethodInfo = getTypeGenericMethodInfo.MakeGenericMethod(new Type[] { derived.GetType() });

        var reflectionStream = new MemoryStream();
        var getTypeStream = new MemoryStream();
        reflectionSpecificMethodInfo.Invoke(null, new object[] { reflectionStream, derived, PrefixStyle.Base128 });
        getTypeSpecificMethodInfo.Invoke(null, new object[] { getTypeStream, derived, PrefixStyle.Base128 });

        Console.WriteLine(reflectionStream.ToArray().Length); // Prints out 15
        Console.WriteLine(getTypeStream.ToArray().Length); // Prints out 37
    }

据我所知,它的工作方式应该相同......我做错了什么? 请注意,我使用的是Proto-buf 2.0.0.431。 谢谢,

2 个答案:

答案 0 :(得分:0)

订购错误

[ProtoContract]
[ProtoInclude(10, typeof(Derived))]
class Base
{
    [ProtoMember(1)]
    public string BaseFirstProperty { get; set; }
    [ProtoMember(2)]
    public string BaseSecProperty { get; set; }
}

[ProtoContract]
class Derived : Base
{
    [ProtoMember(3)]
    public string DerivedFirstProperty { get; set; }
}

答案 1 :(得分:0)

确定;我通过当前的中继代码运行它;我最初得到一个错误处理ImplicitFields,但我已在本地更正了。然后运行它,我得到:

37
37

这告诉我,如果最后一个(625-431)= 194提交,问题已经解决了。别问我哪一个!我建议您尝试使用r625,看看情况如何,我还没有部署,但protobuf-net项目应该构建,或者让我知道您是否希望我通过电子邮件发送给您。

另外:您可能会发现使用非通用API更容易,而不是MakeGenericMethod;那是ProtoBuf.Serializer.NonGenericProtoBuf.RuntimeTypeModel.Default(基本上,通用 Serializer API现在只转发到非通用 API,因为v2核心删除了所有通用代码;除了方便之外,使用通用API绝对没有优势 - 使用反射时没有这种优势。