c# - .NET Core 依赖注入(inject),解析泛型接口(interface)

标签 c# generics dependency-injection .net-core

我在使用 asp.net 核心依赖项注入(inject)时遇到问题,我无法从 IServiceProvider 解析通用接口(interface)。这是我的设置:

通用接口(interface):

public interface IRequest<out TResponse> {...}

public interface IRequestHandler<TRequest, TResult> 
    where TRequest : IRequest<TResult> {...}

具体实现:

public class GetUsersQuery : IRequest<IEnumerable<GetUsersResult>> {...}

public abstract class RequestHandler<TRequest, TResult> 
    : IRequestHandler<TRequest, TResult>
    where TRequest : IRequest<TResult> {...}

public class GetUsersQueryHandler
    : RequestHandler<GetUsersQuery, IEnumerable<GetUsersResult>> {...}

然后我有一个服务工厂,我是这样注册依赖注入(inject)的:

public static void ConfigureServices(IServiceCollection services)
{
    services.AddTransient<IRequestHandler<GetUsersQuery, 
    IEnumerable<GetUsersResult>>, GetUsersQueryHandler>();
}

我可以像这样成功解析我的处理程序:

var handler = 
_services.GetService<IRequestHandler<GetUsersQuery, IEnumerable<GetUsersResult>>>();

但是,我想在这个工厂中有一个通用方法,它接收 IRequest 的具体实现并返回适当的处理程序,而无需事先知道确切的类型,如下所示:

public Task<TResult> Execute<TResult>(IRequest<TResult> request)
{
    var handler =
        _services.GetService<IRequestHandler<IRequest<TResult>, TResult>>();
    return handler.ExecuteAsync(request);
}

然后像这样调用这个方法:

_serviceFactory.Execute(new GetUsersQuery(){});

不幸的是,这不起作用,处理程序未解析且为空。我觉得这应该是可能的。

你能告诉我我做错了什么以及如何实现吗?

最佳答案

此设计可能源自 this博客文章。同一篇博客文章显示了针对您的确切问题的解决方案:

public TResult Process<TResult>(IQuery<TResult> query)
{
    var handlerType = typeof(IQueryHandler<,>)
        .MakeGenericType(query.GetType(), typeof(TResult));

    dynamic handler = container.GetInstance(handlerType);

    return handler.Handle((dynamic)query);
}

在您的情况下,这转化为以下内容:

public Task<TResult> Execute<TResult>(IRequest<TResult> request)
{
    var handlerType = typeof(IRequestHandler<,>)
        .MakeGenericType(request.GetType(), typeof(TResult));

    dynamic handler = _services.GetRequiredService(handlerType);

    return handler.ExecuteAsync((dynamic)query);
}

关于dynamic的使用,博文指出:

Unfortunately we need to call the Handle method using reflection (which is done, in this case, using the C# 4.0 dymamic keyword), because at this point it is impossible to cast the handler instance, since the generic TQuery argument is not available at compile time.

关于c# - .NET Core 依赖注入(inject),解析泛型接口(interface),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53231845/

相关文章:

c# - 通用类的扩展方法

swift - Swinject:使用元类型列表进行解析

c# - Ninject 相当于 MEF AssemblyCatalog

java - 某些 Java 泛型类型转换中的类型安全警告是什么意思?

java - Dagger 2 - 两个提供相同接口(interface)的方法

c# - 将 .Net 核心控制台应用程序部署到 Debian 服务器

c# - 设置断点执行后触发

c# - 如何设置在代码隐藏中声明的依赖属性

C#, json .net - 两个字的值

java - 测试对象是否为空的通用代码?