protobuf-net隐式契约

Mar*_*rko 3 c# serialization protobuf-net

有没有人有一个工作的例子,其中protobuf-net可以用作BinaryFormatter的替代品?这甚至可能吗?

实际上我只需要一个类似于一种消息类型的序列化器

public class A {
  public B[] Bs { get;set; }
  public C[] Cs { get;set; }
}
Run Code Online (Sandbox Code Playgroud)

所有类型都在不同的程序集中定义,并具有许多属性.对于A类和其他使用的类型(B,C),是否有选项可以自动生成包含所有公共属性的proto契约,所以类似于

var formatter = ProtoBuf.Serializer.CreateFormatter<A>()
Run Code Online (Sandbox Code Playgroud)

好吗?

Mar*_*ell 7

首先,protobuf-net并不打算成为100%的替代品BinaryFormatter.它的功能略有不同.

你会满足于做一点反思吗?基本上,有支持ImplicitFields,但目前这只是通过[ProtoContract],并且不能方便地通过RuntimeTypeModel,这有点痛苦,并在我的名单上.虽然,我应该指出,我认为隐含字段有点风险,只有当你知道DTO内部不会改变时才应该这样做!但是:要回答您的问题,您可以迭代您期望的类型,并手动将它们添加到模型中:

static void Main()
{
    Prepare(typeof(A), typeof(B), typeof(C));
    // if you really want to use IFormatter...
    var formatter = RuntimeTypeModel.Default.CreateFormatter(typeof (A));
    var obj = new A {Bs = new B[] {new B()}};
    using (var ms = new MemoryStream())
    {
        formatter.Serialize(ms, obj);
        ms.Position = 0;
        var clone = formatter.Deserialize(ms);
    }
}
static void Prepare(params Type[] types)
{
    if(types != null) foreach(var type in types) Prepare(type);
}
static void Prepare(Type type)
{
    if(type != null && !RuntimeTypeModel.Default.IsDefined(type))
    {
        Debug.WriteLine("Preparing: " + type.FullName);
        // note this has no defined sort, so invent one
        var props = type.GetProperties(); 
        Array.Sort(props, (x, y) => string.Compare(
            x.Name, y.Name, StringComparison.Ordinal));
        var meta = RuntimeTypeModel.Default.Add(type, false);
        int fieldNum = 1;
        for(int i = 0 ; i < props.Length ; i++)
        {
            meta.Add(fieldNum++, props[i].Name);
        }

    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,IFormatter这里的使用完全没必要; 你也可以使用RuntimeTypeModel.Default.Serialize(...)或Serializer.Serialize<T>(...).

作为脚注:我建议更多地重复定义模型.例如:

RuntimeTypeModel.Default.Add(typeof(A)).Add("Bs", "Cs");
RuntimeTypeModel.Default.Add(typeof(B)).Add("Foo");
RuntimeTypeModel.Default.Add(typeof(C)).Add("Bar", "Blap", "Blop");
Run Code Online (Sandbox Code Playgroud)