Skip to main content

# Ex 1

# The Problem Domain

The example we're going to use a simple "addres book". Each person in the address book has a name, an ID, an email address, and a contact phone number.

When using protocol buffers, you first create a .proto file to define the structure of the data you want to store. The protocol buffer compiler then generates a class that automatically encodes and parses the protocol buffer data using a highly efficient binary format. This generated class includes getter and setter methods for the protocol buffer's fields and handles the complexities of reading and writing the protocol buffer as a single unit.

One of the significant advantages of protocol buffers is their ability to extend their format over time while maintaining compatibility with old formats. This means that code can still read data encoded with previous protocol buffer formats, even as newer formats are introduced

## Defining the message structure​

The definitions in a .proto file are simple: you add a message for each data structure you want to serialize, then specify a name and a type for each field in the message. In our example, the .proto file that defines the messages will be: addressbook.proto.

1. under BasicSyntaxConsumer project, resource folder, add a new file named : addressbook.proto

2. add the syntax line:

   `syntax = "proto3";`

3. define the package name : `package tutorial;`

4. define the namespace for the generated class as being `MyExample.AddressBook`:

   `option csharp_namespace = "MyExample.AddressBook";`

   In C#, the generated classes will be placed in a namespace matching the `package` name if `csharp_namespace` is not specified. In our example, the `csharp_namespace` option has been specified to override the default, so the generated code uses a namespace of `MyExample.AddressBook` instead of `Tutorial`

5. add the Person message below:

Person message

    message Person {
      string name = 1;
      int32 id = 2;  // Unique ID number for this person.
      string email = 3;

      enum PhoneType {
        MOBILE = 0;
        HOME = 1;
        WORK = 2;
      }

      message PhoneNumber {
        string number = 1;
        PhoneType type = 2;
      }

      repeated PhoneNumber phones = 4;

      google.protobuf.Timestamp last_updated = 5;
    }

6. import the Well-know type corresponding to timestamp type

    import "google/protobuf/timestamp.proto";

7. Define the "address book"

AddressBook message

    message AddressBook {
      repeated Person people = 1;
    }

Now that we defined the structure, let's go ahead and compile it.

## Compile the protocol buffer​

1. Open a cli and navigate to the folder corrsponding to our BasicSyntaxConsumer/resource project folder cd ..\grpc-start\gRPC\BasicSyntax\BasicSyntaxConsumer
2. run the comand: `protoc -I=. --csharp_out=generatedcode addressbook.proto` or, if you are using powershell cli `.\protoc.exe -I . --csharp_out=generatedcode addressbook.proto`

As a result, under `generatedcode` folder you should see an `AddressBook.cs` file containing some funny code

Generating Addressbook.cs gives us five useful types:

- A static `Addressbook` class that contains metadata about the protocol buffer messages.
- An `AddressBook` class with a read-only `People` property.
- A `Person` class with properties for N`ame, Id, Email and Phones.`
- A `PhoneNumber` class, nested in a static `Person.Types` class.
- A `PhoneType` enum, also nested in `Person.Types`.

## Use the generated file​

Let's use the generated code in our `Program.cs` to get familiar with it.

Using the generated class

    var addressbook = new AddressBook();

    addressbook.People.Add(new Person()
    {
        Name = "John Doe",
        Id = 1,
        Email = "",
        LastUpdated = Timestamp.FromDateTime(DateTime.UtcNow),
        Phones = {
            new Person.Types.PhoneNumber() {
            Number = "123456789",
            Type = Person.Types.PhoneType.Mobile
            }
        }

    });

    addressbook.People.Add(new Person() { Name = "John Doe", Id = 2, Email = "" });
    Console.WriteLine(addressbook);

We can use the `using static MyExample.AddressBook.Person.Types;` to get rid of the long name qualification `Person.Types.PhoneNumber`

DON't

    syntax = "proto3";
    package tutorial;

    import "google/protobuf/timestamp.proto";
    option csharp_namespace = "MyExample.AddressBook";

    message Person {
      string name = 1;
      int32 id = 2;  // Unique ID number for this person.
      string email = 3;

      enum PhoneType {
        MOBILE = 0;
        HOME = 1;
        WORK = 2;
      }

      message PhoneNumber {
        string number = 1;
        PhoneType type = 2;
      }

      repeated PhoneNumber phones = 4;

      google.protobuf.Timestamp last_updated = 5;
    }

    // Our address book file is just one of these.
    message AddressBook {
      repeated Person people = 1;
    }