ASP.NET中Code First模式下gRPC客户端类生成及注入问题
看起来你遇到的问题是找不到自动生成的gRPC客户端类,导致没法用AddGrpcClient实现依赖注入对吧?我之前用Code First做gRPC的时候也踩过这个坑,给你梳理下两种解决方案,对应不同的场景:
方案一:用Code First动态代理实现注入(无需生成客户端类)
微软的Code First gRPC默认是用动态代理的方式创建客户端,根本不需要生成具体的.cs类文件。你可以直接通过AddCodeFirstGrpcClient来注册你的服务接口,步骤很简单:
先确认装对NuGet包
客户端项目得装这两个包:Grpc.Net.ClientFactory:负责客户端工厂的注入功能protobuf-net.Grpc.AspNetCore:支持Code First模式下的DI扩展
要是你用的是.NET 7及以上版本,也可以直接依托Grpc.AspNetCore自带的相关能力。
在Program.cs里注册客户端
把你手动创建Channel的代码替换掉,改成在DI容器里注册:builder.Services.AddCodeFirstGrpcClient<IFullProjectInfoService>(options => { options.Address = new Uri("http://localhost:5053"); });直接注入接口使用
之后在需要调用gRPC服务的类里,直接把IFullProjectInfoService通过构造函数注入就行,再也不用手动创建Channel和客户端了:public class YourBusinessService { private readonly IFullProjectInfoService _projectInfoService; // 构造函数注入接口 public YourBusinessService(IFullProjectInfoService projectInfoService) { _projectInfoService = projectInfoService; } public async Task<FullProjectInfoResponse> GetProjectData(int projectId, int userId) { return await _projectInfoService.GetFullProjectInfoAsync( new FullProjectInfoRequest { ProjectId = projectId, UserId = userId } ); } }
方案二:生成强类型客户端类(适合需要具体类的场景)
要是你确实需要看得见的客户端类文件,也可以配置生成步骤:
确保服务端有对应的.proto文件
如果你是纯Code First没写.proto,可以用工具从接口生成对应的.proto,或者直接在服务端项目里手动编写和接口方法、消息类型匹配的.proto定义。配置客户端项目的代码生成
在客户端项目的.csproj文件里加这段配置,让Grpc.Tools自动帮你生成客户端类:<ItemGroup> <Protobuf Include="..\YourServiceProject\Protos\fullprojectinfo.proto" GrpcServices="Client" /> </ItemGroup>注意路径要指向你服务端的.proto文件,
GrpcServices="Client"表示只生成客户端代码。用生成的客户端类做注入
生成后你会得到类似FullProjectInfoServiceClient的类,这时就可以用AddGrpcClient来注册了:builder.Services.AddGrpcClient<FullProjectInfoServiceClient>(options => { options.Address = new Uri("http://localhost:5053"); });之后直接注入这个客户端类就能调用服务了。
几个常见坑的排查
- 要是用方案一找不到
AddCodeFirstGrpcClient方法,十有八九是没装protobuf-net.Grpc.AspNetCore这个NuGet包,装完就有了。 - 一定要确保客户端项目引用了包含
IFullProjectInfoService接口的服务端类库,不然编译会报找不到接口的错。 - 检查服务端的接口方法有没有正确标记
[ServiceContract]和[OperationContract](或者gRPC专属的属性),不然动态代理识别不了你的服务方法。
备注:内容来源于stack exchange,提问作者Nazar Masukov

