C# を使用した gRPC サービス

このドキュメントでは、C# で gRPC アプリを作成するために必要な概念を説明します。 ここで取り上げるトピックは、C-coreベースと ASP.NET Core ベースの両方の gRPC アプリに適用されます。

警告

ASP.NET Core gRPC には、Azure App Service または IIS と共に使用するための追加の要件があります。 gRPCを使用できる場所の詳細については、「.NET での gRPC でサポートされているプラットフォーム」を参照してください。

proto ファイル

gRPC では、API 開発に対してコントラクト優先のアプローチが使われます。 プロトコル バッファー (protobuf) は、既定でインターフェイス定義言語 (IDL) として使用されます。 *.proto ファイルには次のものが含まれます。

  • gRPC サービスの定義。
  • クライアントとサーバー間で送信されるメッセージ。

protobuf ファイルの構文の詳細については、「.NET アプリの Protobuf メッセージを作成する」を参照してください。

たとえば、gRPC サービスの概要に関するページで使用されている greet.proto ファイルについて考えてみます。

  • Greeter サービスを定義します。
  • Greeter サービスで SayHello 呼び出しを定義します。
  • SayHello では、HelloRequest メッセージを送信し、HelloReply メッセージを受信します。
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;
}

コードのコメントを英語以外の言語に翻訳し表示したい場合、こちらの GitHub ディスカッション イシューにてお知らせください。

C# アプリに .proto ファイルを追加する

*.proto ファイルは、<Protobuf> 項目グループにそれを追加することで、プロジェクトに含まれます。

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

既定で、<Protobuf> 参照によって、具象クライアントとサービス基本クラスが生成されます。 参照要素の GrpcServices 属性を使用して、C# アセットの生成を制限できます。 有効な GrpcServices オプションは次のとおりです。

  • Both (存在しない場合の既定値)
  • Server
  • Client
  • None

.proto ファイルに対する C# ツール サポート

*.proto ファイルから C# アセットを生成するために、ツール パッケージ Grpc.Tools が必要です。 生成されるアセット (ファイル) は:

  • プロジェクトがビルドされるたびに、必要に応じて生成されます。
  • プロジェクトに追加されないか、ソース管理にチェックインされません。
  • obj ディレクトリに格納されるビルド成果物です。

このパッケージは、サーバー プロジェクトとクライアント プロジェクトの両方で必要です。 Grpc.AspNetCore メタパッケージには、Grpc.Tools への参照が含まれます。 サーバー プロジェクトでは、Visual Studio の Package Manager を使用するか、プロジェクト ファイルに <PackageReference> を追加することによって、Grpc.AspNetCore を追加できます。

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

クライアント プロジェクトでは、gRPC クライアントを使用するために必要なその他のパッケージと共に、Grpc.Tools を直接参照する必要があります。 ツール パッケージは実行時に不要であるため、依存関係に PrivateAssets="All" でマークが付けられます。

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

生成された C# アセット

ツール パッケージは、含まれている *.proto ファイルに定義されたメッセージを表す C# 型を生成します。

サーバー側アセットの場合、抽象サービスの基本型が生成されます。 基本型には、 .proto ファイルに含まれるすべての gRPC 呼び出しの定義が含まれます。 この基本型から派生し、gRPC 呼び出しのロジックを実装する具象サービス実装を作成します。 greet.proto の場合、前述の例では、仮想 SayHello メソッドを含む抽象 GreeterBase 型が生成されます。 具象実装 GreeterService は、メソッドをオーバーライドし、gRPC 呼び出しを処理するロジックを実装します。

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

クライアント側アセットの場合、具象クライアント型が生成されます。 .proto ファイル内の gRPC 呼び出しは、具象型のメソッドに変換され、これを呼び出すことができます。 greet.proto の場合、前述の例では、具象 GreeterClient 型が生成されます。 GreeterClient.SayHelloAsync を呼び出して、サーバーへの gRPC 呼び出しを開始します。

// 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();

既定で、<Protobuf> 項目グループに含まれている各 *.proto ファイルに対して、サーバーとクライアントのアセットが生成されます。 サーバー プロジェクトでサーバー アセットのみが生成されるようにするには、GrpcServices 属性を Server に設定します。

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

同様に、クライアントプロジェクトでは属性を Client に設定します。

その他の技術情報

このドキュメントでは、C# で gRPC アプリを作成するために必要な概念を説明します。 ここで取り上げるトピックは、C-coreベースと ASP.NET Core ベースの両方の gRPC アプリに適用されます。

警告

ASP.NET Core gRPC には、Azure App Service または IIS と共に使用するための追加の要件があります。 gRPCを使用できる場所の詳細については、「.NET での gRPC でサポートされているプラットフォーム」を参照してください。

proto ファイル

gRPC では、API 開発に対してコントラクト優先のアプローチが使われます。 プロトコル バッファー (protobuf) は、既定でインターフェイス定義言語 (IDL) として使用されます。 *.proto ファイルには次のものが含まれます。

  • gRPC サービスの定義。
  • クライアントとサーバー間で送信されるメッセージ。

protobuf ファイルの構文の詳細については、「.NET アプリの Protobuf メッセージを作成する」を参照してください。

たとえば、gRPC サービスの概要に関するページで使用されている greet.proto ファイルについて考えてみます。

  • Greeter サービスを定義します。
  • Greeter サービスで SayHello 呼び出しを定義します。
  • SayHello では、HelloRequest メッセージを送信し、HelloReply メッセージを受信します。
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;
}

コードのコメントを英語以外の言語に翻訳し表示したい場合、こちらの GitHub ディスカッション イシューにてお知らせください。

C# アプリに .proto ファイルを追加する

*.proto ファイルは、<Protobuf> 項目グループにそれを追加することで、プロジェクトに含まれます。

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

既定で、<Protobuf> 参照によって、具象クライアントとサービス基本クラスが生成されます。 参照要素の GrpcServices 属性を使用して、C# アセットの生成を制限できます。 有効な GrpcServices オプションは次のとおりです。

  • Both (存在しない場合の既定値)
  • Server
  • Client
  • None

.proto ファイルに対する C# ツール サポート

*.proto ファイルから C# アセットを生成するために、ツール パッケージ Grpc.Tools が必要です。 生成されるアセット (ファイル) は:

  • プロジェクトがビルドされるたびに、必要に応じて生成されます。
  • プロジェクトに追加されないか、ソース管理にチェックインされません。
  • obj ディレクトリに格納されるビルド成果物です。

このパッケージは、サーバー プロジェクトとクライアント プロジェクトの両方で必要です。 Grpc.AspNetCore メタパッケージには、Grpc.Tools への参照が含まれます。 サーバー プロジェクトでは、Visual Studio の Package Manager を使用するか、プロジェクト ファイルに <PackageReference> を追加することによって、Grpc.AspNetCore を追加できます。

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

クライアント プロジェクトでは、gRPC クライアントを使用するために必要なその他のパッケージと共に、Grpc.Tools を直接参照する必要があります。 ツール パッケージは実行時に不要であるため、依存関係に PrivateAssets="All" でマークが付けられます。

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

生成された C# アセット

ツール パッケージは、含まれている *.proto ファイルに定義されたメッセージを表す C# 型を生成します。

サーバー側アセットの場合、抽象サービスの基本型が生成されます。 基本型には、 .proto ファイルに含まれるすべての gRPC 呼び出しの定義が含まれます。 この基本型から派生し、gRPC 呼び出しのロジックを実装する具象サービス実装を作成します。 greet.proto の場合、前述の例では、仮想 SayHello メソッドを含む抽象 GreeterBase 型が生成されます。 具象実装 GreeterService は、メソッドをオーバーライドし、gRPC 呼び出しを処理するロジックを実装します。

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

クライアント側アセットの場合、具象クライアント型が生成されます。 .proto ファイル内の gRPC 呼び出しは、具象型のメソッドに変換され、これを呼び出すことができます。 greet.proto の場合、前述の例では、具象 GreeterClient 型が生成されます。 GreeterClient.SayHelloAsync を呼び出して、サーバーへの gRPC 呼び出しを開始します。

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();
}

既定で、<Protobuf> 項目グループに含まれている各 *.proto ファイルに対して、サーバーとクライアントのアセットが生成されます。 サーバー プロジェクトでサーバー アセットのみが生成されるようにするには、GrpcServices 属性を Server に設定します。

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

同様に、クライアントプロジェクトでは属性を Client に設定します。

その他の技術情報