protobuf-net: невозможно сериализовать данные типа. Как определить данные типа с помощью буферов протокола? - PullRequest
2 голосов
/ 28 июня 2011

Я пытаюсь создать простую сетку в памяти, которую можно сериализовать с использованием буферов протокола.

Идея состоит в том, что пользователь может создавать / определять столбцы любого типа (примитивы или пользователь, определенные, если они помечены буферами протокола).

Моя проблема в том, что вы не можете сериализовать данные типа с помощью буферов протокола, так как мне этого добиться?

Код ниже показывает, как я надеялся закодировать столбцы сетки.

Большое спасибо.

[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 Ответ

1 голос
/ 28 июня 2011

В этом подходе есть пара проблем; да, в стандартных буферах протокола любые метаданные 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

(псевдокод, неполный)

Я бы с радостью провел вас по многим вопросам, но вы также можете посмотреть эту запись в блоге , чтобы узнать, используете ли вы DataTable (насколько мне это не нравится для доступа к данным) может сэкономить немного усилий здесь.

...