7.NET中GRPC进阶,可空类型,返回集合
1.添加两个类,一个类型可空,一个不可空
public class Person1 { public int Id { get; set; } public double Money { get; set; } public float Weight { get; set; } public bool Gender { get; set; } public long PhoneNum { get; set; } public string Email { get; set; } public System.DateTime Birthday { get; set; } }
public class Person2 { public int? Id { get; set; } public double? Money { get; set; } public float? Weight { get; set; } public bool? Gender { get; set; } public long? PhoneNum { get; set; } public string? Email { get; set; } public DateTime? Birthday { get; set; } }
2.在GrpcServer项目中的Apis文件夹中添加
public interface IPersonService { Person1 GetPerson1(); Person2 GetPerson2(); }
public class PersonServiceImpl:IPersonService { public Person1 GetPerson1() { var person = new Person1 { Id = 1, Money = 3000.00d, Weight = 1.78f, Gender = true, PhoneNum = 13823784433, Email = "1310734881@qq.com", Birthday = DateTime.Parse("2000-02-20").ToUniversalTime() }; return person; } public Person2 GetPerson2() { var person = new Person2 { Id = 1, Money = 3000.00d, Weight = 1.78f, Gender = true, PhoneNum = 13823784433, Email = "1310734881@qq.com", Birthday = DateTime.Parse("2000-02-20") }; return person; } }
3.然后再Protos文件中添加person.proto文件
syntax = "proto3"; option csharp_namespace = "GrpcServer"; package person; // 时间类型 import "google/protobuf/timestamp.proto"; // 无参/无返回值 import "google/protobuf/empty.proto"; // 引用可空类型 import "google/protobuf/wrappers.proto"; message Person1Dto{ int32 id=1; double money=2; float weight=3; bool gender=4; int64 phone_num=5; string email=6; google.protobuf.Timestamp birthday=7; } // 出参1,返回类型 message Person1Response{ Person1Dto person =1; } //入参,传入参数 message Person1Request{ } // 可空类型 message Person2Dto{ google.protobuf.Int32Value id = 1; google.protobuf.DoubleValue money = 2; google.protobuf.FloatValue weight = 3; google.protobuf.BoolValue gender = 4; google.protobuf.Int64Value phone_num = 5; google.protobuf.StringValue email = 6; google.protobuf.Timestamp birthday = 7; }
//出参,返回类型 message Person2Response{ Person2Dto person =1; } //入参,参数 集合请求对象 message CollectionRequest{ } // 集合响应对象 message CollectionResponse{ repeated Person1Dto person=1; map<int32,Person1Dto> dict=2; } //服务 service PersonService{ rpc GetPerson1(google.protobuf.Empty) returns (Person1Response); rpc GetPerson2(google.protobuf.Empty) returns (Person2Response); // 返回集合 rpc GetCollection(CollectionRequest) returns (CollectionResponse); }
看GrpcServer.csproj内是否生成
<ItemGroup> <PackageReference Include="Grpc.AspNetCore" Version="2.56.0" /> <ProtoBuf Include="Protos/user.proto" GrpcService="Server" /> <ProtoBuf Include="Protos/person.proto" GrpcService="Server" /> </ItemGroup>
在Services文件夹内添加PersonServiceGrpc.cs
public class PersonServiceGrpc:PersonService.PersonServiceBase { private readonly IPersonService _personService; public PersonServiceGrpc(IPersonService personService) { _personService = personService; } public override Task<Person1Response> GetPerson1(Empty request, ServerCallContext context) { Person1 person1 = _personService.GetPerson1(); Person1Response response = new(); response.Person = new() { Id = person1.Id, Money = person1.Money, Weight = person1.Weight, Gender = person1.Gender, PhoneNum = person1.PhoneNum, Email = person1.Email, // timestamp 类型需要UTC时间 Birthday = DateTime.Parse("2000-02-20").ToUniversalTime().ToTimestamp() }; return Task.FromResult(response); } public override Task<Person2Response> GetPerson2(Empty request, ServerCallContext context) { Person2 person2 = _personService.GetPerson2(); Person2Response response = new(); response.Person = new() { Id = person2.Id, Money = person2.Money, Weight = person2.Weight, Gender = person2.Gender, PhoneNum = person2.PhoneNum, Email = person2.Email, // timestamp 类型需要UTC时间 Birthday = DateTime.Parse("2000-02-20").ToUniversalTime().ToTimestamp() }; return Task.FromResult(response); } public override Task<CollectionResponse> GetCollection(CollectionRequest request, ServerCallContext context) { CollectionResponse response = new(); Person1Dto dto1 = new() { Id = 1, Money = 3000.00d, Weight = 1.78f, Gender = true, PhoneNum = 13823784433, Email = "1310734881@qq.com", Birthday = DateTime.Parse("2000-02-20").ToUniversalTime().ToTimestamp() }; Person1Dto dto2 = new() { Id = 2, Money = 2000.00d, Weight = 2.78f, Gender = true, PhoneNum = 13823782222, Email = "1310734881@qq.com", Birthday = DateTime.Parse("2022-02-22").ToUniversalTime().ToTimestamp() }; List<Person1Dto> list = new() {dto1, dto2}; response.Person.AddRange(list); response.Dict.Add(1,dto1); response.Dict.Add(2,dto2); return Task.FromResult(response); } }
在Program.cs添加注册服务和添加管道
var builder = WebApplication.CreateBuilder(args); builder.Services.AddGrpc();//添加GRPC服务 //设置GRPC为http2.0 builder.WebHost.UseKestrel(p => { p.ConfigureEndpointDefaults(opt => { opt.Protocols = HttpProtocols.Http2; }); }); builder.Services.AddTransient<IUserService, UserServiceImpl>(); builder.Services.AddTransient<IPersonService, PersonServiceImpl>(); var app = builder.Build(); app.MapGrpcService<UserServiceGrpc>(); app.MapGrpcService<PersonServiceGrpc>(); app.Run();
客户端
gRPC 与 HttpClientFactory 的集成提供了一种创建 gRPC 客户端的集中方式。 它可用作 配置独立gRPC 客户端实例
安装包:Grpc.Net.ClientFactory
GrpcClient客户端项目中的Protos文件夹中添加person.proto文件
syntax = "proto3"; option csharp_namespace = "GrpcClient"; package person; // 时间类型 import "google/protobuf/timestamp.proto"; // 无参/无返回值 import "google/protobuf/empty.proto"; // 引用可空类型 import "google/protobuf/wrappers.proto"; message Person1Dto{ int32 id=1; double money=2; float weight=3; bool gender=4; int64 phone_num=5; string email=6; google.protobuf.Timestamp birthday=7; } // 出参1 message Person1Response{ Person1Dto person =1; } message Person1Request{ } // 可空类型 message Person2Dto{ google.protobuf.Int32Value id = 1; google.protobuf.DoubleValue money = 2; google.protobuf.FloatValue weight = 3; google.protobuf.BoolValue gender = 4; google.protobuf.Int64Value phone_num = 5; google.protobuf.StringValue email = 6; google.protobuf.Timestamp birthday = 7; } message Person2Response{ Person2Dto person =1; } // 集合请求对象 message CollectionRequest{ } // 集合响应对象 message CollectionResponse{ repeated Person1Dto person=1; map<int32,Person1Dto> dict=2; } service PersonService{ rpc GetPerson1(google.protobuf.Empty) returns (Person1Response); rpc GetPerson2(google.protobuf.Empty) returns (Person2Response); // 返回集合 rpc GetCollection(CollectionRequest) returns (CollectionResponse); }
生成后查看GrpcClient.csproj是否以下
<ItemGroup> <Protobuf Include="Protos\person.proto"> <GrpcServices>Client</GrpcServices> <Access>Public</Access> <ProtoCompile>True</ProtoCompile> <CompileOutputs>True</CompileOutputs> <OutputDir>obj\Debug\net7.0\</OutputDir> <Generator>MSBuild:Compile</Generator> </Protobuf> <Protobuf Include="Protos\user.proto"> <GrpcServices>Client</GrpcServices> <Access>Public</Access> <ProtoCompile>True</ProtoCompile> <CompileOutputs>True</CompileOutputs> <OutputDir>obj\Debug\net7.0\</OutputDir> <Generator>MSBuild:Compile</Generator> </Protobuf> </ItemGroup>
若要注册 gRPC 客户端,可在 Program.cs 中的应用入口点处的 WebApplicationBuilder 的实例中使用通用的 AddGrpcClient 扩展方法,并指定 gRPC 类型化客户端类和服务地址
Action<GrpcClientFactoryOptions> opt = p => { p.Address = new Uri("http://localhost:5023"); }; builder.Services.AddGrpcClient<UserService.UserServiceClient>(opt); builder.Services.AddGrpcClient<PersonService.PersonServiceClient>(opt);
添加PersonController控制器
[ApiController] [Route("[controller]/[action]")] public class PersonController : ControllerBase { private readonly PersonService.PersonServiceClient _personServiceClient; public PersonController(PersonService.PersonServiceClient personServiceClient) { _personServiceClient = personServiceClient; } [HttpGet] public async Task<IActionResult> GetPerson1() { // 创建通信频道 // var channel = GrpcChannel.ForAddress("http://localhost:5023"); // var client = new PersonService.PersonServiceClient(channel); // var response = client.GetPerson1Async(new Empty()); // // 等待获取头 // var resultHeaders = await response.ResponseHeadersAsync; // var resultResponse = await response.ResponseAsync; var response = _personServiceClient.GetPerson1(new Empty()); return Ok(response.Person); } [HttpGet] public IActionResult GetPerson2() { // 创建通信频道 // var channel = GrpcChannel.ForAddress("http://localhost:5023"); // var client = new PersonService.PersonServiceClient(channel); var response = _personServiceClient.GetPerson2(new Empty()); return Ok(response.Person); } [HttpGet] public IActionResult GetCollection() { // 创建通信频道 // var channel = GrpcChannel.ForAddress("http://localhost:5023"); // var client = new PersonService.PersonServiceClient(channel); var response = _personServiceClient.GetCollection(new CollectionRequest()); return Ok(new{response.Person,response.Dict}); } }