开发者

Can ProtoBuf-Net deserialize to a flat class?

protobuf-net uses nested protobuf constructs to support inheritance. However, can it be made to push properties into a flat target class that has the same properties as the inherited "serialized" version?

See the test example below. Needless to say the result of the Flat namespace is null for both properties.


Possible solution: copy data into flat.B first on a property by property basis.

Note: this is not the prefered option.


using System;

namespace hierarchy
{
    using ProtoBuf;

    [ProtoContract]
    public class A
    {
        [ProtoMember(1)]
        public string prop1 { get; set; }
    }

    [ProtoContract]
    public class B : A
    {
        public B()
        {
        }

        [ProtoMember(1)]
        public string prop2 { get; set; }

        public override string ToString()
        {
            return "prop1=" + prop1 + ", prop2=" + prop2;
        }

    }
}

namespace flat
{
    using ProtoBuf;

    [ProtoContract]
    public class B
    {
        [ProtoMember(1)]
        public string prop1 { get; set; }

        [ProtoMember(2)]
        public string prop2 { get; set; }

        public override string ToString()
        {
            return "prop1=" + prop1 + ", prop2=" + prop2;
        }
    }
}

namespace TestProtoSerialization
{
    using ProtoBuf;
    using System.IO;

    public class Test2
    {
        public void Test()
        {
 开发者_运维知识库           var hb = new hierarchy.B();
            hb.prop1 = "prop1";
            hb.prop2 = "prop2";

            var ms = new MemoryStream();

            Serializer.Serialize<hierarchy.B>(ms, hb);

            var flatB = Serializer.Deserialize<flat.B>(ms);

            Console.WriteLine(hb.ToString());     // <----- Output: prop1=prop1, prop2=prop2  
            Console.WriteLine(flatB.ToString());  // <----- Output: prop1=, prop2=
        }
    }

    public class Program
    {
        private static void Main(string[] args)
        {
            var o2 = new Test2();
            o2.Test();
        }
    }

}


Not directly, and I'm not sure there is a great need to. Maybe I am missing something in the example...

To pick up on the key point - even forgetting about inheritance you've broken the contract - te fields in your exampl are 1 & 1 in one model and 1 & 2 in the other.

It really depends what your objective is; if you just want to push the data over, then sure you can set up a RuntimeTypeModel that only knows about the derived type (disable automatic configuration and add the fields manually). This will then only work for the derived type (obviously), but will output the data as expected by the flat model:

var model = TypeModel.Create();
model.Add(typeof(B), false)
    .Add("prop1", "prop2");

Then use model.Serialize etc.

However, writing a flat conversion method on c#, or using AutoMapper would be more obvious. I would only use the above if my objective is to remove the inheritance from the output, for example for interoperability reasons.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜