简体   繁体   English

Protobuf-net - 如何使用 oneof

[英]Protobuf-net - How to use oneof

I did a quick search about the usage of oneof in Protobuf-net and it appears it's supported as of v2.3.0 , but I can't for the life of me find any examples on exactly how one would use it!我做了关于使用快速搜索oneofProtobuf-net ,看来它的支持为V2.3.0的,但我不能为我的生活找到一个确切会如何使用它任何的例子!

My requirements are pretty simple, and maybe this can also be solved with [ProtoInclude] but I'm not quite sure exactly how this would work.我的要求非常简单,也许这也可以用[ProtoInclude]解决,但我不太确定这到底是如何工作的。 I've got the following class:我有以下课程:

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

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

Where Message can be 1 of 8 different known types.其中Message可以是 8 种不同的已知类型之一。 The types do not inherit from each other at all and although the code can be changed, there's nothing all types have in common.这些类型根本不相互继承,虽然代码可以更改,但所有类型都没有共同点。

Using Google.Protobuf I'd expect to do something similar to this , where I have a property called Instrument that can be one of two types in the example above and then use InstrumentOneofCase to figure out which type I was given.使用Google.Protobuf我希望做一些与此类似的事情,其中​​我有一个名为Instrument的属性,它可以是上面示例中的两种类型之一,然后使用InstrumentOneofCase找出我得到的类型。 But how do I achieve the same thing in Protobuf-net ?但是我如何在Protobuf-net实现同样的目标?

EDIT: I'll leave the original question as it, but perhaps a better question which more people can relate to is: how would you achieve the same thing as with this MS example in Protobuf-net?编辑:我将保留原来的问题,但也许更多人能想到的一个更好的问题是:你将如何实现与 Protobuf-net 中的这个 MS 示例相同的事情? Both in terms of writing the class itself and in terms of determining what concrete type the parameter is in the end?无论是在编写类本身方面还是在确定参数最终是什么具体类型方面?

The way to play with this is to take the message from the MS example you cite, and run it through protogen to see what it does - which we can do very conveniently here: https://protogen.marcgravell.com/ (note I'm adding syntax = "proto3"; at the top of the file, which is omitted in the MS example).解决这个问题的方法是从您引用的 MS 示例中获取消息,然后通过 protogen 运行它以查看它的作用 - 我们可以在这里非常方便地完成: https ://protogen.marcgravell.com/(注意我'm 在文件顶部添加syntax = "proto3";在 MS 示例中省略)。

This gives us, among other things:这给我们,除其他外:

    [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);

So we can see that it is basically using conditional serialization built on top of the DiscriminatedUnionObject type.所以我们可以看到它基本上使用了建立在DiscriminatedUnionObject类型之上的条件序列化。 There are actually a bunch of related types named DiscriminatedUnion* - depending on what you need to overlap, but since they're all message types here: DiscriminatedUnionObject works for us.实际上有一堆名为DiscriminatedUnion*的相关类型 - 取决于您需要重叠的内容,但由于它们都是此处的消息类型: DiscriminatedUnionObject对我们有用。


There's also an optional " oneof should use enum" option (under: oddly, "Options"), which if enabled, also adds:还有一个可选的“ oneof should use enum”选项(在:奇怪的是,“选项”下),如果启用,还会添加:

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

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

Without that, you would have to use the ShouldSerialize*() methods to resolve the active case. ShouldSerialize*() ,您将不得不使用ShouldSerialize*()方法来解决活动案例。

Hopefully that clarifies how oneof can be used with protobuf-net.希望这能阐明oneof如何与 protobuf-net 一起使用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM