【问题标题】:Use generic to reduce repeated code - Method accepting two generic parameters使用泛型减少重复代码 - 接受两个泛型参数的方法
【发布时间】:2021-06-21 21:56:39
【问题描述】:

我有一个方法,它有一组重复的语句,它们要求重构,但我不知道如何泛型应该执行重复任务的方法的参数。

这是我的代码:

private void RegisterServices(IServiceCollection services)
{
    services.AddTransient<CommonApiMessageHandler>();

    var baseAddress = Configuration["ApiSetup:BaseAddress"];

    services.AddHttpClient<ILookupService, LookupService>("Api.Lookup", client =>
    {
        client.BaseAddress = new Uri(baseAddress);
    }).AddHttpMessageHandler<CommonApiMessageHandler>();

    services.AddHttpClient<IBusinessLookupService, BusinessLookupService>("Api.Lookup", client =>
    {
        client.BaseAddress = new Uri(baseAddress);
    }).AddHttpMessageHandler<CommonApiMessageHandler>();

    services.AddHttpClient<IApiUserService, ApiUserService>("Api.ApiUser", client =>
    {
        client.BaseAddress = new Uri(baseAddress);
    }).AddHttpMessageHandler<CommonApiMessageHandler>();

    services.AddHttpClient<IRequestService, RequestService>("Api.Request", client =>
    {
        client.BaseAddress = new Uri(baseAddress);
    }).AddHttpMessageHandler<CommonApiMessageHandler>();

    services.AddHttpClient<IResourceService, ResourceService>("Api.Resource", client =>
    {
        client.BaseAddress = new Uri(baseAddress);
    }).AddHttpMessageHandler<CommonApiMessageHandler>();

    services.AddHttpClient<IApproverTemplateService, ApproverTemplateService>("Api.ApproverTemplate", client =>
    {
        client.BaseAddress = new Uri(baseAddress);
    }).AddHttpMessageHandler<CommonApiMessageHandler>();

    services.AddHttpClient<IAttachmentService, AttachmentService>("Api.Attachment", client =>
    {
        client.BaseAddress = new Uri(baseAddress);
    }).AddHttpMessageHandler<CommonApiMessageHandler>();

    services.AddHttpClient<IDacBudgetService, DacBudgetServiceClient>("Api.DaCBudget", client =>
    {
        client.BaseAddress = new Uri(baseAddress);
    }).AddHttpMessageHandler<CommonApiMessageHandler>();
}

我觉得应该是这样的:

private static void NewMethod(IServiceCollection services, string baseAddress, Generic T, Generic U)
{
    services.AddHttpClient<T, U>("Api.Lookup", client =>
    {
        client.BaseAddress = new Uri(baseAddress);
    }).AddHttpMessageHandler<CommonApiMessageHandler>();
}

这可能吗?

【问题讨论】:

  • 是的。应该是private static void NewMethod&lt;T, U&gt;(IServiceCollection services, string baseAddress, T serviceInterface, U serviceImpl) where U : T。您在尖括号中定义泛型参数,然后可以像使用类型一样使用它们。 where U : T 是一个约束,意味着 U(您的服务类)必须实现 T(您的服务接口),这样可以避免在您不小心尝试输入不兼容的类型时出错。
  • @ckuri 可能想将其作为您的答案,而不是评论。
  • @ckuri 我在使用serviceInterface & serviceImpl services.AddHttpClient&lt;serviceInterface, serviceImpl&gt;(name, client =&gt; { ... } 时出错:serviceInterface 是一个变量,但用作一个类型

标签: c# generics dependency-injection


【解决方案1】:

您不仅可以使用泛型,还可以将其定义为extension method,因此您可以像调用其他服务一样调用它。

public static class MyExtensions
{
    public static IServiceCollection AddMyService<TInterface,TImplementation>(this IServiceCollection services, string serviceName, string baseAddress)
        where TInterface: class 
        where TImplementation : class, TInterface
    {
        services.AddHttpClient<TInterface, TImplementation>(serviceName, client =>
        {
            client.BaseAddress = new Uri(baseAddress);
        }).AddHttpMessageHandler<CommonApiMessageHandler>();

        return services;
    }
}

然后这样称呼它:

services.AddMyService<IApiUserService, ApiUserService>("Api.ApiUser", baseAddress);
services.AddMyService<IRequestService, RequestService>("Api.Request", baseAddress);

//etc....

或者,由于我们返回 IServiceCollection,您可以将它们链接起来:

services
    .AddMyService<IApiUserService, ApiUserService>("Api.ApiUser", baseAddress)
    .AddMyService<IRequestService, RequestService>("Api.Request", baseAddress);

【讨论】:

  • 扩展方法中需要有return语句吗?
  • 已编辑。很高兴返回 IServiceCollection 以便调用者可以链接调用。
  • 这是完美的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-31
相关资源
最近更新 更多