Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
P
protobuf
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
submodule
protobuf
Commits
54a3d8e7
Commit
54a3d8e7
authored
Aug 13, 2019
by
Sydney Acksman
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add proto2 doc
parent
c132a4aa
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
185 additions
and
0 deletions
+185
-0
proto2.md
docs/csharp/proto2.md
+185
-0
No files found.
docs/csharp/proto2.md
0 → 100644
View file @
54a3d8e7
Proto2 support in Google.Protobuf is finally here! This document outlines the new changes brought about
by this initial release of proto2 support. The generated code and public API associated with proto2
is experimental and subject to change in the future. APIs may be added, removed, or adjusted as feedback is received.
Generated code may also be modified, adding, removing, or adjusting APIs as feedback is received.
# Generated code
### Messages
Messages in proto2 files are very similar to their proto3 counterparts. However, they have some added properties
and methods to handle field presence.
A normal single value proto2 fields will have a normal property for getting and setting, as well as a
`HasValue`
property for checking presence, and a
`Clear`
method for clearing the value.
```
proto
message
Foo
{
optional
Bar
bar
=
1
;
required
Baz
baz
=
2
;
}
```
```
cs
var
foo
=
new
Foo
();
Assert
.
IsNull
(
foo
.
Bar
);
Assert
.
False
(
foo
.
HasBar
);
foo
.
Bar
=
new
Bar
();
Assert
.
True
(
foo
.
HasBar
);
foo
.
ClearBar
();
```
### Messages with extension ranges
Messages which define extension ranges implement the
`IExtendableMessage`
interface as shown below.
See inline comments for more info.
```
cs
public
interface
IExtendableMessage
<
T
>
:
IMessage
<
T
>
where
T
:
IExtendableMessage
<
T
>
{
// Gets the value of a single value extension. If the extension isn't present, this returns the default value.
TValue
GetExtension
<
TValue
>(
Extension
<
T
,
TValue
>
extension
);
// Gets the value of a repeated extension. If the extension hasn't been set, this returns null to prevent unnecessary allocations.
RepeatedField
<
TValue
>
GetExtension
<
TValue
>(
RepeatedExtension
<
T
,
TValue
>
extension
);
// Gets the value of a repeated extension. This will initialize the value of the repeated field and will never return null.
RepeatedField
<
TValue
>
GetOrInitializeExtension
<
TValue
>(
RepeatedExtension
<
T
,
TValue
>
extension
);
// Sets the value of the extension
void
SetExtension
<
TValue
>(
Extension
<
T
,
TValue
>
extension
,
TValue
value
);
// Returns whether the extension is present in the message
bool
HasExtension
<
TValue
>(
Extension
<
T
,
TValue
>
extension
);
// Clears the value of the extension, removing it from the message
void
ClearExtension
<
TValue
>(
Extension
<
T
,
TValue
>
extension
);
// Clears the value of the repeated extension, removing it from the message. Calling GetExtension after this will always return null.
void
ClearExtension
<
TValue
>(
RepeatedExtension
<
T
,
TValue
>
extension
);
}
```
### Extensions
Extensions are generated in static containers like reflection classes and type classes.
For example for a file called
`foo.proto`
containing extensions in the file scope, a
`FooExtensions`
class is created containing the extensions defined in the file scope.
For easy access, this class can be used with
`using static`
to bring all extensions into scope.
```
proto
option
csharp_namespace
=
"FooBar"
;
extend
Foo
{
optional
Baz
foo_ext
=
124
;
}
message
Baz
{
extend
Foo
{
repeated
Baz
repeated_foo_ext
=
125
;
}
}
```
```
cs
public
static
partial
class
FooExtensions
{
public
static
readonly
Extension
<
Foo
,
Baz
>
FooExt
=
/* initialization */
;
}
public
partial
class
Baz
{
public
partial
static
class
Extensions
{
public
static
readonly
RepeatedExtension
<
Foo
,
Baz
>
RepeatedFooExt
=
/* initialization */
;
}
}
```
```
cs
using
static
FooBar
.
FooExtensions
;
using
static
FooBar
.
Baz
.
Extensions
;
var
foo
=
new
Foo
();
foo
.
SetExtension
(
FooExt
,
new
Baz
());
foo
.
GetOrInitializeExtension
(
RepeatedFooExt
).
Add
(
new
Baz
());
```
# APIs
### Message initialization
Checking message initialization is not handled automatically by the library, but can be done manually via the
`IsInitialized`
extension method in
`MessageExtensions`
. Please note, parsers and input streams don't check messages
for initialization on their own and throw errors. Instead it's up to you to handle messages with missing required fields
in whatever way you see fit.
### Extension registries
Just like in Java, extension registries can be constructed to parse extensions when reading new messages
from input streams. The API is fairly similar to the Java API with some added bonuses with C# syntax sugars.
```
proto
message
Baz
{
extend
Foo
{
optional
Baz
foo_ext
=
124
;
}
}
```
```
cs
var
registry
=
new
ExtensionRegistry
()
{
Baz
.
Extensions
.
FooExt
};
var
foo
=
Foo
.
Factory
.
WithExtensionRegistry
(
registry
).
ParseFrom
(
input
);
Assert
.
True
(
foo
.
HasExtension
(
Bas
.
Extensions
.
FooExt
));
var
fooNoRegistry
=
Foo
.
Factory
.
ParseFrom
(
input
);
Assert
.
False
(
foo
.
HasExtension
(
Bas
.
Extensions
.
FooExt
));
```
### Custom options
The original
`CustomOptions`
APIs are now deprecated. Using the new generated extension identifiers,
you can access extensions safely through the GetOption APIs. Note that cloneable values such as
repeated fields and messages will be deep cloned.
Example based on custom options usage example
[
here
](
https://github.com/protocolbuffers/protobuf/issues/5007#issuecomment-411604515
)
.
```
cs
foreach
(
var
service
in
input
.
Services
)
{
Console
.
WriteLine
(
$"
{
service
.
Name
}
"
);
foreach
(
var
method
in
service
.
Methods
)
{
var
rule
=
method
.
GetOption
(
AnnotationsExtensions
.
Http
);
if
(
rule
!=
null
)
{
Console
.
WriteLine
(
$"
{
method
.
Name
}
:
{
rule
}
"
);
}
else
{
Console
.
WriteLine
(
$"
{
method
.
Name
}
: no HTTP binding"
);
}
}
}
```
### Reflection
Reflection APIs have been included to access the new portions of the library.
*
FieldDescriptor.Extension
*
Gets the extension identifier behind an extension field, allowing it to be added to an ExtensionRegistry
*
FieldDescriptor.IsExtension
*
Returns whether a field is an extension of another type.
*
FieldDescriptor.ExtendeeType
*
Returns the extended type of an extension field
*
IFieldAccessor.HasValue
*
Returns whether a field's value is set. For proto3 fields, throws an InvalidOperationException.
*
FileDescriptor.Syntax
*
Gets the syntax of a file
*
FileDescriptor.Extensions
*
An immutable list of extensions defined in the file
*
MessageDescriptor.Extensions
*
An immutable list of extensions defined in the message
```
cs
var
extensions
=
Baz
.
Descriptor
.
Extensions
.
GetExtensionsInDeclarationOrder
(
Foo
.
Descriptor
);
var
registry
=
new
ExtensionRegistry
();
registry
.
AddRange
(
extensions
.
Select
(
f
=>
f
.
Extension
));
var
baz
=
Foo
.
Descriptor
.
Parser
.
WithExtensionRegistry
(
registry
).
ParseFrom
(
input
);
foreach
(
var
field
in
extensions
)
{
if
(
field
.
Accessor
.
HasValue
(
baz
))
{
Console
.
WriteLine
(
$"
{
field
.
Name
}
:
{
field
.
Accessor
.
GetValue
(
baz
)}
"
);
}
}
```
\ No newline at end of file
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment