gRPC-Dienste mit C#

In diesem Artikel werden die Konzepte erläutert, die zum Schreiben von gRPC-Apps in C# erforderlich sind. Die hier behandelten Themen gelten für gRPC-Apps, die auf C-Core und auf ASP.NET Core basieren.

PROTO-Datei

gRPC verwendet einen Vertrag zuerst-Ansatz für die API-Entwicklung. Protokollpuffer (protobuf) werden standardmäßig als IDL (Interface Definition Language) verwendet. Die Datei .proto enthält Folgendes:

  • Die Definition des gRPC-Diensts
  • Die zwischen Clients und Servern übermittelten Nachrichten

Weitere Informationen zur Syntax von Protobuf-Dateien finden Sie unter Erstellen von Protobuf-Nachrichten für .NET-Apps.

Sehen Sie sich beispielsweise die Datei greet.proto an, die in den ersten Schritten mit dem gRPC-Dienst verwendet wird:

  • Die Datei definiert einen Greeter-Dienst.
  • Der Greeter-Dienst definiert einen SayHello-Aufruf.
  • SayHello sendet eine HelloRequest-Nachricht und empfängt eine HelloReply-Nachricht:
syntax = "proto3";

option csharp_namespace = "GrpcGreeter";

package greet;

// The greeting service definition.
service Greeter {
  // Sends a greeting
  rpc SayHello (HelloRequest) returns (HelloReply);
}

// The request message containing the user's name.
message HelloRequest {
  string name = 1;
}

// The response message containing the greetings.
message HelloReply {
  string message = 1;
}

Wenn Sie möchten, dass Codekommentare in anderen Sprachen als Englisch angezeigt werden, informieren Sie uns in diesem GitHub-Issue.

Hinzufügen einer .proto-Datei zu einer C#-App

Die .proto-Datei wird in ein Projekt eingefügt, indem sie zur Elementgruppe <Protobuf> hinzugefügt wird:

<ItemGroup>
  <Protobuf Include="Protos\greet.proto" GrpcServices="Server" />
</ItemGroup>

Durch einen <Protobuf>-Verweis werden standardmäßig ein konkreter Client und eine Dienstbasisklasse generiert. Mit dem Attribut GrpcServices des Verweiselements kann das Generieren von C#-Objekten beschränkt werden. Gültige Optionen für GrpcServices sind:

  • Both (Standardwert, wenn nicht vorhanden)
  • Server
  • Client
  • None

C#-Toolunterstützung für .proto-Dateien

Das Toolpaket Grpc.Tools ist zum Generieren der C#-Ressourcen aus .proto-Dateien erforderlich. Die generierten Ressourcen (Dateien):

  • Werden jedes Mal nach Bedarf generiert, wenn der Buildvorgang für das Projekt ausgeführt wird.
  • Werden nicht zum Projekt hinzugefügt oder in der Quellcodeverwaltung eingecheckt.
  • Sind Buildartefakte, die im obj-Verzeichnis enthalten sind.

Dieses Paket ist für die Server- und Clientprojekte erforderlich. Das Metapaket Grpc.AspNetCore enthält einen Verweis auf Grpc.Tools. Serverprojekte können Grpc.AspNetCore mithilfe des Paket-Managers in Visual Studio oder durch Hinzufügen von <PackageReference> zur Projektdatei hinzufügen:

<PackageReference Include="Grpc.AspNetCore" Version="2.32.0" />

Clientprojekte sollten direkt auf Grpc.Tools sowie auf die anderen zum Verwenden des gRPC-Clients erforderlichen Pakete verweisen. Das Toolpaket ist nicht zur Laufzeit erforderlich, darum ist die Abhängigkeit mit PrivateAssets="All" markiert:

<PackageReference Include="Google.Protobuf" Version="3.18.0" />
<PackageReference Include="Grpc.Net.Client" Version="2.52.0" />
<PackageReference Include="Grpc.Tools" Version="2.40.0">
  <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
  <PrivateAssets>all</PrivateAssets>
</PackageReference>

Generierte C#-Ressourcen

Das Toolpaket generiert die C#-Typen, die die Nachrichten darstellen, die in den enthaltenen .proto-Dateien definiert werden.

Für serverseitige Ressourcen wird ein abstrakter Dienstbasistyp generiert. Der Basistyp enthält die Definitionen für alle gRPC-Aufrufe, die in der .proto-Datei enthalten sind. Erstellen Sie eine konkrete Dienstimplementierung, die von diesem Basistyp abgeleitet wird und die Logik für die gRPC-Aufrufe implementiert. Für das zuvor beschriebene Beispiel greet.proto wird ein abstrakter GreeterBase-Typ generiert, der eine virtuelle SayHello-Methode enthält. Eine konkrete GreeterService-Implementierung überschreibt die Methode und implementiert die Logik, die den gRPC-Aufruf verarbeitet.

public class GreeterService : Greeter.GreeterBase
{
    private readonly ILogger<GreeterService> _logger;
    public GreeterService(ILogger<GreeterService> logger)
    {
        _logger = logger;
    }

    public override Task<HelloReply> SayHello(HelloRequest request, ServerCallContext context)
    {
        return Task.FromResult(new HelloReply
        {
            Message = "Hello " + request.Name
        });
    }
}

Für clientseitige Ressourcen wird ein konkreter Clienttyp generiert. Die gRPC-Aufrufe in der .proto-Datei werden in Methoden für den konkreten Typ übersetzt, die aufgerufen werden können. Für das zuvor beschriebene Beispiel greet.proto wird ein konkreter GreeterClient-Typ generiert. Rufen Sie GreeterClient.SayHelloAsync auf, um einen gRPC-Aufruf an den Server zu initiieren.

// The port number must match the port of the gRPC server.
using var channel = GrpcChannel.ForAddress("https://localhost:7042");
var client = new Greeter.GreeterClient(channel);
var reply = await client.SayHelloAsync(
                  new HelloRequest { Name = "GreeterClient" });
Console.WriteLine("Greeting: " + reply.Message);
Console.WriteLine("Press any key to exit...");
Console.ReadKey();

Server- und Clientressourcen werden standardmäßig für alle .proto-Dateien generiert, die in der Elementgruppe <Protobuf> enthalten sind. Das GrpcServices-Attribut wird auf Server festgelegt, um sicherzustellen, dass nur die Serverressourcen in einem Serverprojekt generiert werden.

<ItemGroup>
  <Protobuf Include="Protos\greet.proto" GrpcServices="Server" />
</ItemGroup>

Entsprechend wird das Attribut bei Clientprojekten auf Client festgelegt.

Zusätzliche Ressourcen

In diesem Artikel werden die Konzepte erläutert, die zum Schreiben von gRPC-Apps in C# erforderlich sind. Die hier behandelten Themen gelten für gRPC-Apps, die auf C-Core und auf ASP.NET Core basieren.

PROTO-Datei

gRPC verwendet einen Vertrag zuerst-Ansatz für die API-Entwicklung. Protokollpuffer (protobuf) werden standardmäßig als IDL (Interface Definition Language) verwendet. Die Datei .proto enthält Folgendes:

  • Die Definition des gRPC-Diensts
  • Die zwischen Clients und Servern übermittelten Nachrichten

Weitere Informationen zur Syntax von Protobuf-Dateien finden Sie unter Erstellen von Protobuf-Nachrichten für .NET-Apps.

Sehen Sie sich beispielsweise die Datei greet.proto an, die in den ersten Schritten mit dem gRPC-Dienst verwendet wird:

  • Die Datei definiert einen Greeter-Dienst.
  • Der Greeter-Dienst definiert einen SayHello-Aufruf.
  • SayHello sendet eine HelloRequest-Nachricht und empfängt eine HelloReply-Nachricht:
syntax = "proto3";

option csharp_namespace = "GrpcGreeter";

package greet;

// The greeting service definition.
service Greeter {
  // Sends a greeting
  rpc SayHello (HelloRequest) returns (HelloReply);
}

// The request message containing the user's name.
message HelloRequest {
  string name = 1;
}

// The response message containing the greetings.
message HelloReply {
  string message = 1;
}

Wenn Sie möchten, dass Codekommentare in anderen Sprachen als Englisch angezeigt werden, informieren Sie uns in diesem GitHub-Issue.

Hinzufügen einer .proto-Datei zu einer C#-App

Die .proto-Datei wird in ein Projekt eingefügt, indem sie zur Elementgruppe <Protobuf> hinzugefügt wird:

<ItemGroup>
  <Protobuf Include="Protos\greet.proto" GrpcServices="Server" />
</ItemGroup>

Durch einen <Protobuf>-Verweis werden standardmäßig ein konkreter Client und eine Dienstbasisklasse generiert. Mit dem Attribut GrpcServices des Verweiselements kann das Generieren von C#-Objekten beschränkt werden. Gültige Optionen für GrpcServices sind:

  • Both (Standardwert, wenn nicht vorhanden)
  • Server
  • Client
  • None

C#-Toolunterstützung für .proto-Dateien

Das Toolpaket Grpc.Tools ist zum Generieren der C#-Ressourcen aus .proto-Dateien erforderlich. Die generierten Ressourcen (Dateien):

  • Werden jedes Mal nach Bedarf generiert, wenn der Buildvorgang für das Projekt ausgeführt wird.
  • Werden nicht zum Projekt hinzugefügt oder in der Quellcodeverwaltung eingecheckt.
  • Sind Buildartefakte, die im obj-Verzeichnis enthalten sind.

Dieses Paket ist für die Server- und Clientprojekte erforderlich. Das Metapaket Grpc.AspNetCore enthält einen Verweis auf Grpc.Tools. Serverprojekte können Grpc.AspNetCore mithilfe des Paket-Managers in Visual Studio oder durch Hinzufügen von <PackageReference> zur Projektdatei hinzufügen:

<PackageReference Include="Grpc.AspNetCore" Version="2.28.0" />

Clientprojekte sollten direkt auf Grpc.Tools sowie auf die anderen zum Verwenden des gRPC-Clients erforderlichen Pakete verweisen. Das Toolpaket ist nicht zur Laufzeit erforderlich, darum ist die Abhängigkeit mit PrivateAssets="All" markiert:

<PackageReference Include="Google.Protobuf" Version="3.11.4" />
<PackageReference Include="Grpc.Net.Client" Version="2.52.0" />
<PackageReference Include="Grpc.Tools" Version="2.28.1">
  <PrivateAssets>all</PrivateAssets>
  <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>

Generierte C#-Ressourcen

Das Toolpaket generiert die C#-Typen, die die Nachrichten darstellen, die in den enthaltenen .proto-Dateien definiert werden.

Für serverseitige Ressourcen wird ein abstrakter Dienstbasistyp generiert. Der Basistyp enthält die Definitionen für alle gRPC-Aufrufe, die in der .proto-Datei enthalten sind. Erstellen Sie eine konkrete Dienstimplementierung, die von diesem Basistyp abgeleitet wird und die Logik für die gRPC-Aufrufe implementiert. Für das zuvor beschriebene Beispiel greet.proto wird ein abstrakter GreeterBase-Typ generiert, der eine virtuelle SayHello-Methode enthält. Eine konkrete GreeterService-Implementierung überschreibt die Methode und implementiert die Logik, die den gRPC-Aufruf verarbeitet.

public class GreeterService : Greeter.GreeterBase
{
    private readonly ILogger<GreeterService> _logger;
    public GreeterService(ILogger<GreeterService> logger)
    {
        _logger = logger;
    }

    public override Task<HelloReply> SayHello(HelloRequest request, ServerCallContext context)
    {
        return Task.FromResult(new HelloReply
        {
            Message = "Hello " + request.Name
        });
    }
}

Für clientseitige Ressourcen wird ein konkreter Clienttyp generiert. Die gRPC-Aufrufe in der .proto-Datei werden in Methoden für den konkreten Typ übersetzt, die aufgerufen werden können. Für das zuvor beschriebene Beispiel greet.proto wird ein konkreter GreeterClient-Typ generiert. Rufen Sie GreeterClient.SayHelloAsync auf, um einen gRPC-Aufruf an den Server zu initiieren.

static async Task Main(string[] args)
{
    // The port number(5001) must match the port of the gRPC server.
    using var channel = GrpcChannel.ForAddress("https://localhost:5001");
    var client = new Greeter.GreeterClient(channel);
    var reply = await client.SayHelloAsync(
                      new HelloRequest { Name = "GreeterClient" });
    Console.WriteLine("Greeting: " + reply.Message);
    Console.WriteLine("Press any key to exit...");
    Console.ReadKey();
}

Server- und Clientressourcen werden standardmäßig für alle .proto-Dateien generiert, die in der Elementgruppe <Protobuf> enthalten sind. Das GrpcServices-Attribut wird auf Server festgelegt, um sicherzustellen, dass nur die Serverressourcen in einem Serverprojekt generiert werden.

<ItemGroup>
  <Protobuf Include="Protos\greet.proto" GrpcServices="Server" />
</ItemGroup>

Entsprechend wird das Attribut bei Clientprojekten auf Client festgelegt.

Zusätzliche Ressourcen