protobuf-net:无法序列化类型数据,如何使用协议缓冲区定义类型数据?

时间:2011-06-27 20:17:11

标签: c# protocol-buffers protobuf-net

我正在尝试创建一个简单的内存网格,可以使用协议缓冲区进行序列化。

这个想法是用户可以创建/定义任何类型的列(基元或用户定义的列,只要它们是标记的协议缓冲区)。

我的问题是您无法使用协议缓冲区序列化类型数据,那么我该如何实现呢?

代码如下,显示我希望如何编码网格的列。

非常感谢。

[TestClass]
public class UnitTest1
{
    [TestMethod]
    public void TestMethod1()
    {
        Column colOrderId = new Column("OrderId", typeof(uint));
        Column colOrderDesc = new Column("OrderDesc", typeof(string));
        Column colPrice = new Column("Price", typeof(Price));
        Column colOrderDateTime = new Column("OrderDateTime", typeof(DateTime));

        var s = colOrderId.ToBArray();
    }
}

[ProtoContract, Serializable]
public sealed class Column
{
    public Column(string name, Type type)
    {
        Name = name;
        Type = type;
    }

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

    [ProtoMember(2)]
    public Type Type { get; private set; }
}

[ProtoContract, Serializable]
public sealed class Price
{
    public Price(double value, string currency)
    {
        Value = value;
        Currency = currency;
    }

    [ProtoMember(1)]
    public double Value { get; private set; }

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

public static class ProtoBufEx
{
    public static byte[] ToBArray<T>(this T o)
    {
        using (MemoryStream ms = new MemoryStream())
        {
            ProtoBuf.Serializer.Serialize(ms, o);
            return ms.ToArray();
        }
    }
}

1 个答案:

答案 0 :(得分:1)

这种方法存在一些问题;是的,在标准协议缓冲区中,任何类型的Type元数据都有点顽皮,因为它不是真正的可互操作性,但我在v2 的基础上选择加入了一点松散 - 允许您发送object等,只要在内部它仍然知道您的意思。

然而,这对于逐个单元格的工作来说会变得很昂贵,甚至内置优化(例如,它只发送一次相同类型的元数据)。

但是,IMO,更好的选择是将自己限制在一个已知类型的列表中,这些类型都是提前知道的。如果你可以 ,那么有一些有趣的继承技巧非常有效并且非常适合这种情况。但基本上你有类似的东西:

[ProtoContract]
[ProtoInclude(4, typeof(Column<int>))] // etc
abstract class Column {
    [ProtoMember(1)]
    public string Name {get;private set;}

    public abstract object Value {get;private set;}
}
[ProtoContract]
class Column<T> : Column {
    [ProtoMember(1)]
    public T TypedValue { get;private set;}
    override Value {...shim to TypedValue...}
}
// etc

(伪代码,不完整)

我很高兴地向您介绍了很多内容,但您可能还想查看this blog entry以查看是否使用DataTable(就像我不喜欢数据访问一样)可能会节省这里有一些努力。