This browser is no longer supported.
Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical support.
Download Microsoft Edge
More info about Internet Explorer and Microsoft Edge
This content is an excerpt from the eBook, gRPC for WCF developers, available on
.NET Docs
or as a free downloadable PDF that can be read offline.
Download PDF
Handling dynamic property types (that is, properties of type
object
) in Windows Communication Foundation (WCF) is complicated. For example, you must specify serializers and provide
KnownType
attributes.
Protocol Buffer (Protobuf) provides two simpler options for dealing with values that might be of more than one type. The
Any
type can represent any known Protobuf message type. And you can use the
oneof
keyword to specify that only one of a range of fields can be set in any message.
Any
is one of Protobuf's "well-known types": a collection of useful, reusable message types with implementations in all supported languages. To use the
Any
type, you must import the
google/protobuf/any.proto
definition.
syntax = "proto3";
import "google/protobuf/any.proto";
message Stock {
// Stock-specific data
message Currency {
// Currency-specific data
message ChangeNotification {
int32 id = 1;
google.protobuf.Any instrument = 2;
In the C# code, the Any
class provides methods for setting the field, extracting the message, and checking the type.
public void FormatChangeNotification(ChangeNotification change)
if (change.Instrument.Is(Stock.Descriptor))
FormatStock(change.Instrument.Unpack<Stock>());
else if (change.Instrument.Is(Currency.Descriptor))
FormatCurrency(change.Instrument.Unpack<Currency>());
throw new ArgumentException("Unknown instrument type");
Protobuf's internal reflection code uses the Descriptor
static field on each generated type to resolve Any
field types. There's also a TryUnpack<T>
method, but that creates an uninitialized instance of T
even when it fails. It's better to use the Is
method as shown earlier.
Oneof
Oneof fields are a language feature: the compiler handles the oneof
keyword when it generates the message class. Using oneof
to specify the ChangeNotification
message might look like this:
message Stock {
// Stock-specific data
message Currency {
// Currency-specific data
message ChangeNotification {
int32 id = 1;
oneof instrument {
Stock stock = 2;
Currency currency = 3;
Fields within the oneof
set must have unique field numbers in the overall message declaration.
When you use oneof
, the generated C# code includes an enum that specifies which of the fields has been set. You can test the enum to find which field is set. Fields that aren't set return null
or the default value, rather than throwing an exception.
public void FormatChangeNotification(ChangeNotification change)
switch (change.InstrumentCase)
case ChangeNotification.InstrumentOneofCase.None:
return;
case ChangeNotification.InstrumentOneofCase.Stock:
FormatStock(change.Stock);
break;
case ChangeNotification.InstrumentOneofCase.Currency:
FormatCurrency(change.Currency);
break;
default:
throw new ArgumentException("Unknown instrument type");
Setting any field that's part of a oneof
set will automatically clear any other fields in the set. You can't use repeated
with oneof
. Instead, you can create a nested message with either the repeated field or the oneof
set to work around this limitation.
Previous