1

我对oneofin的用法进行了快速搜索Protobuf-net,似乎从 v2.3.0 开始支持它,但我终其一生都找不到任何关于如何使用它的示例!

我的要求很简单,也许这也可以解决,[ProtoInclude]但我不太确定这将如何工作。我有以下课程:

[ProtoContract]
public class ProgressUIMessage
{
    [ProtoMember(1)]
    public int Id {get; set;}

    [ProtoMember(2)]
    public object Message {get; set;}
}

其中Message可以是 8 种不同已知类型中的 1 种。这些类型根本不会相互继承,尽管可以更改代码,但所有类型都没有任何共同点。

使用Google.Protobuf我希望做与此类似的事情,其中​​我有一个名为的属性Instrument,它可以是上面示例中的两种类型之一,然后InstrumentOneofCase用来确定我被赋予了哪种类型。但是我如何实现同样的目标Protobuf-net呢?

编辑:我将保留原来的问题,但也许更多人可以涉及到的更好的问题是:你将如何实现与Protobuf-net 中的这个 MS 示例 相同的事情?无论是在编写类本身方面还是在确定参数最终是什么具体类型方面?

4

1 回答 1

2

解决这个问题的方法是从你引用的 MS 示例中获取消息,并通过 protogen 运行它以查看它的作用——我们可以在这里非常方便地做到这一点:https ://protogen.marcgravell.com/ (注意我'syntax = "proto3";在文件顶部添加,在 MS 示例中省略)。

这给了我们,除其他外:

    [global::ProtoBuf.ProtoMember(2, Name = @"stock")]
    public Stock Stock
    {
        get => __pbn__instrument.Is(2) ? ((Stock)__pbn__instrument.Object) : default;
        set => __pbn__instrument = new global::ProtoBuf.DiscriminatedUnionObject(2, value);
    }
    public bool ShouldSerializeStock() => __pbn__instrument.Is(2);
    public void ResetStock() => global::ProtoBuf.DiscriminatedUnionObject.Reset(ref __pbn__instrument, 2);

    private global::ProtoBuf.DiscriminatedUnionObject __pbn__instrument;

    [global::ProtoBuf.ProtoMember(3, Name = @"currency")]
    public Currency Currency
    {
        get => __pbn__instrument.Is(3) ? ((Currency)__pbn__instrument.Object) : default;
        set => __pbn__instrument = new global::ProtoBuf.DiscriminatedUnionObject(3, value);
    }
    public bool ShouldSerializeCurrency() => __pbn__instrument.Is(3);
    public void ResetCurrency() => global::ProtoBuf.DiscriminatedUnionObject.Reset(ref __pbn__instrument, 3);

所以我们可以看到它基本上是使用建立在类型之上的条件序列化DiscriminatedUnionObject。实际上有一堆相关的类型被命名DiscriminatedUnion*- 取决于你需要重叠的内容,但因为它们都是这里的消息类型:DiscriminatedUnionObject为我们工作。


还有一个可选的“oneof应该使用枚举”选项(奇怪的是,“选项”下),如果启用,还会添加:

    public InstrumentOneofCase InstrumentCase => (InstrumentOneofCase)__pbn__instrument.Discriminator;

    public enum InstrumentOneofCase
    {
        None = 0,
        Stock = 2,
        Currency = 3,
    }

否则,您将不得不使用这些ShouldSerialize*()方法来解决活动案例。

希望这oneof能阐明如何与 protobuf-net 一起使用。

于 2021-10-20T14:28:13.037 回答