Microsoft依赖注入解析泛型类型返回null

时间:2017-05-30 20:58:50

标签: c# generics reflection dependency-injection

我正在尝试将我以前在Autofac中执行的操作转换为Microsoft依赖注入。我有一堆基于接口的RequestHandler:

public interface IRequestHandler<TParameter, TResult>
    where TResult : IResponse
    where TParameter : IRequest
{
    TResult Handle(TParameter query);
}

我已经注册了所有请求处理程序和所有IResponse对象以及我的IRequest对象:

 var request handlers = ReflectionUtils.GetClosedTypes(typeof(IRequestHandler<,>), assemblies);
        foreach (var requestHandler in requestHandlers)
        {
            serviceCollection.AddScoped(requestHandler);
        }

我收集所有要注册的类型:

 public static IEnumerable<Type> GetClosedTypes(Type openGeneric, params Assembly[] assemblies)
    {
        if (assemblies == null || assemblies.Length == 0)
        {
            return new Type[0];
        }

        var list = new List<Type>();
        foreach (var assembly in assemblies)
        {
            if (!assembly.IsDynamic)
            {
                var types = ReflectionUtils.GetExportedTypes(assembly);

                var q = from type in types
                        from i in type.GetInterfaces()
                        where i.IsGenericType && i.GetGenericTypeDefinition() == openGeneric
                        select type;

                list.AddRange(q);
            }
        }

        return list;
    }

我可以单步执行代码并查看它们已注册。然后,我希望能够通过一个RequestDispatcher来检索它们,这个RequestDispatcher从ServideProvider中检索项目并调用Handle方法:

 public TResult Dispatch<TParameter, TResult>(TParameter query)
        where TParameter : IRequest
        where TResult : IResponse
    {
        //Get the approproprite command handler by resolving it from the autofac _serviceProvider based on the IQuery and IQueryResult
        var handler = _serviceProvider.GetService<IRequestHandler<TParameter, TResult>>();
        return handler.Handle(query);
    }

但是GetService返回null。我怀疑它与物品在容器中的注册方式有关。以下是我在Autofac中注册事物的方法:

builder.RegisterAssemblyTypes(MyAssembly)
            .AsClosedTypesOf(typeof(IRequestHandler<,>))
            .InstancePerLifetimeScope()
            .AsImplementedInterfaces();

1 个答案:

答案 0 :(得分:2)

您应该首先更改将类型注册到DI容器中的方式。

我认为仅注册具体类型将不允许服务提供商解析其接口(如果未明确注册)。

尝试提供所需的ServiceCollection所有类型:

public static IDictionary<Type, Type> GetClosedTypesRegistrations(Type openGeneric, params Assembly[] assemblies)
{
    if (assemblies == null || assemblies.Length == 0)
    {
        return new Dictionary<Type, Type>();
    }

    return assemblies
        .Where(a => !a.IsDynamic)
        .SelectMany(ReflectionUtils.GetExportedTypes)
        .SelectMany(t => t.GetInterfaces(), (t, i) => new { service = i, type = t } )
        .Where(r => r.service.IsGenericType && r.service.GetGenericTypeDefinition() == openGeneric)
        .ToDictionary(r => r.service, r => r.type);
}

内部ConfigureServices

var requestHandlers = ReflectionUtils.GetClosedTypesRegistrations(typeof(IRequestHandler<,>), assemblies);
foreach (var requestHandler in requestHandlers)
{
    serviceCollection.AddScoped(requestHandler.Key, requestHandler.Value);
}