如何创建带有类型参数的键控服务
如何创建带有类型参数的键控服务
看起来你正在构建一个基于泛型接口的服务体系,多个类各自实现了带不同具体类型参数的IEndpointManager,想要让这些服务能被正确地注册、查找和调用对吧?我来给你梳理下具体的实现步骤:
首先先明确你已经有的基础代码:
你定义了这样一个泛型接口:
public interface IEndpointManager<TRequest, TResponse> { Task<TResponse?> CreateRequestAsync(TRequest request); }
还有一个实现类的示例(你给出的代码虽不完整,但大概是这样的结构):
public class PatientFinderPlusEndpoint : IEndpointManager<RequestModel<PatientFinderRequest>, ...>
接下来一步步实现键控服务的创建:
- 第一步:补全你的实现类
确保每个实现类都明确指定泛型接口的具体类型参数,并且实现接口的方法,比如完整的PatientFinderPlusEndpoint应该是这样:
public class PatientFinderPlusEndpoint : IEndpointManager<RequestModel<PatientFinderRequest>, PatientFinderResponse> { public async Task<PatientFinderResponse?> CreateRequestAsync(RequestModel<PatientFinderRequest> request) { // 这里写你的具体业务逻辑,比如调用数据访问层、处理请求等 return await FetchPatientData(request.Payload); } }
- 第二步:在DI容器中注册服务
如果是用ASP.NET Core的依赖注入,你可以在Program.cs(或者旧版本的Startup.cs)里逐个注册每个泛型实现:
// 注册PatientFinder的实现 builder.Services.AddScoped<IEndpointManager<RequestModel<PatientFinderRequest>, PatientFinderResponse>, PatientFinderPlusEndpoint>(); // 如果还有其他实现,比如用户查询的服务,同样注册 builder.Services.AddScoped<IEndpointManager<RequestModel<UserLookupRequest>, UserLookupResponse>, UserLookupEndpoint>();
- 第三步:创建工厂类实现动态键控查找
如果需要根据不同的请求/响应类型动态获取对应的服务实例(也就是按类型键来匹配),最好不要在业务代码里直接依赖IServiceProvider,而是封装一个工厂类来处理这个逻辑:
public class EndpointManagerFactory { private readonly IServiceProvider _serviceProvider; // 通过构造函数注入IServiceProvider public EndpointManagerFactory(IServiceProvider serviceProvider) { _serviceProvider = serviceProvider; } // 泛型方法:直接通过类型参数获取对应的服务 public IEndpointManager<TRequest, TResponse> GetManager<TRequest, TResponse>() { return _serviceProvider.GetRequiredService<IEndpointManager<TRequest, TResponse>>(); } // 非泛型重载:如果是反射场景或者无法提前确定类型的情况,可以用Type对象来获取 public object GetManager(Type requestType, Type responseType) { var targetServiceType = typeof(IEndpointManager<,>).MakeGenericType(requestType, responseType); return _serviceProvider.GetRequiredService(targetServiceType); } }
别忘了把这个工厂类也注册到DI容器里:
builder.Services.AddScoped<EndpointManagerFactory>();
- 第四步:在业务代码中使用工厂获取服务
现在你就可以在需要的地方注入EndpointManagerFactory,然后根据具体的类型获取对应的IEndpointManager实例了:
public class RequestProcessor { private readonly EndpointManagerFactory _endpointFactory; public RequestProcessor(EndpointManagerFactory endpointFactory) { _endpointFactory = endpointFactory; } public async Task ProcessIncomingRequest(object request) { // 根据请求的具体类型匹配对应的服务 if (request is RequestModel<PatientFinderRequest> patientRequest) { var manager = _endpointFactory.GetManager<RequestModel<PatientFinderRequest>, PatientFinderResponse>(); var response = await manager.CreateRequestAsync(patientRequest); // 处理返回的响应结果 HandlePatientResponse(response); } else if (request is RequestModel<UserLookupRequest> userRequest) { var manager = _endpointFactory.GetManager<RequestModel<UserLookupRequest>, UserLookupResponse>(); var response = await manager.CreateRequestAsync(userRequest); // 处理用户查询的响应 HandleUserResponse(response); } } }
另外给你一个小技巧:如果你的实现类很多,不想一个个手动注册,可以用反射批量扫描并注册所有实现了IEndpointManager<,>的类,这样更高效:
// 扫描当前程序集中所有符合条件的实现类 var endpointImplementations = Assembly.GetExecutingAssembly() .GetTypes() .Where(type => type.IsClass && !type.IsAbstract && type.GetInterfaces().Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IEndpointManager<,>))); foreach (var implementationType in endpointImplementations) { // 获取对应的泛型接口类型 var interfaceType = implementationType.GetInterfaces() .First(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IEndpointManager<,>)); // 注册到DI容器 builder.Services.AddScoped(interfaceType, implementationType); }
内容来源于stack exchange
相关产品推荐
相关产品推荐

