通用查询处理程序的LightInject注册

时间:2015-04-30 21:05:38

标签: generics dependencies registration code-injection

我对CQRS模式很陌生,并且遇到了将所有这些与我选择的依赖注入容器捆绑在一起的问题。(LightInject)

我拥有的是通用查询对象

public interface IQuery<TResult>
{
}

由GenericQuery实现

public class GenericQuery<TSrcEntity> : IQuery<IEnumerable<TSrcEntity>>
{
    public Expression<Func<TSrcEntity, bool>> Filter { get; set; }
    public Func<IQueryable<TSrcEntity>, IOrderedQueryable<TSrcEntity>> OrderBy { get; set; }
    public IEnumerable<string> IncludeProperties { get; set; }
}

然后我通过Query Dispatcher处理所有这些,它通过依赖项解析器确定要使用哪个处理程序

public class QueryDispatcher:IQueryDispatcher
{

    public TResult Dispatch<TQuery, TResult>(TQuery query) where TQuery : IQuery<TResult>
    {
        var handler = DependencyResolver.Get<IQueryHandler<TQuery,TResult>>();
        return handler.Retreive(query);
    }
}

处理程序实现

 public class GenericQueryHandler<TSrcEntity> : IQueryHandler<GenericQuery<TSrcEntity>, IEnumerable<TSrcEntity>> where TSrcEntity : class
{
    public IEnumerable<TSrcEntity> Retreive(GenericQuery<TSrcEntity> query)
    {
        return GetDocuments();
    }

我对LightInject的注册看起来像这样

class Program
{
    static void Main(string[] args)
    {
        var container = new ServiceContainer();

        //service
        container.Register<ITestService, TestService>();

        //query
        container.Register(typeof(IQuery<>), typeof(GenericQuery<>));

        //handler This one works, but I dont want to register everything explicity.
        container.Register(typeof(IQueryHandler<GenericQuery<Document>, IEnumerable<Document>>), typeof(GenericQueryHandler<Document>));

        //dispatcher
        container.Register<IQueryDispatcher, QueryDispatcher>();

        DependencyResolver.SetResolver(container);

        var service = container.GetInstance<ITestService>();

        var a = service.GetDocuments();

    }

只要我明确注册我的处理程序,一切都很顺利

//handler This one works, but I dont want to register everything explicity.
        container.Register(typeof(IQueryHandler<GenericQuery<Document>, IEnumerable<Document>>), typeof(GenericQueryHandler<Document>));

但我不想为每个实体做这件事。对LightInject更熟悉的人可以帮忙吗?

可以在Generic Query Problem

找到示例程序

由于

1 个答案:

答案 0 :(得分:1)

我知道这是一篇旧文章,但是我遇到了同样的问题,并且找到了解决方案。我在这里找到了解决方案:https://github.com/seesharper/LightInject/issues/350

该页面上的代码是这样的:

public static class ContainerExtensions
{
    public static void RegisterCommandHandlers(this IServiceRegistry serviceRegistry)
    {
        var commandTypes =
            Assembly.GetCallingAssembly()
                .GetTypes()
                .Select(t => GetGenericInterface(t, typeof(ICommandHandler<>)))
                .Where(m => m != null);
        RegisterHandlers(serviceRegistry, commandTypes);
        serviceRegistry.Register<ICommandExecutor>(factory => new CommandExecutor((IServiceFactory)serviceRegistry));            
        serviceRegistry.Decorate(typeof(ICommandHandler<>), typeof(TransactionalCommandDecorator<>));
    }


    public static void RegisterQueryHandlers(this IServiceRegistry serviceRegistry)
    {
        var commandTypes =
            Assembly.GetCallingAssembly()
                .GetTypes()
                .Select(t => GetGenericInterface(t, typeof(IQueryHandler<,>)))
                .Where(m => m != null);
        RegisterHandlers(serviceRegistry, commandTypes);
        serviceRegistry.Register<IQueryExecutor>(factory => new QueryExecutor((IServiceFactory)serviceRegistry));
        serviceRegistry.Decorate(typeof(IQueryHandler<,>), typeof(QueryHandlerLogDecorator<,>));
    }

    private static Tuple<Type, Type> GetGenericInterface(Type type, Type genericTypeDefinition)
    {           
        var closedGenericInterface = 
            type.GetInterfaces()
                .SingleOrDefault(i => i.IsGenericType && i.GetGenericTypeDefinition() == genericTypeDefinition);
        if (closedGenericInterface != null)
        {
            var constructor = type.GetConstructors().FirstOrDefault();
            if (constructor != null)
            {
                var isDecorator = constructor.GetParameters().Select(p => p.ParameterType).Contains(closedGenericInterface);
                if (!isDecorator)
                {
                    return Tuple.Create(closedGenericInterface, type);
                }
            }                
        }
        return null;
    }

    private static void RegisterHandlers(IServiceRegistry registry,  IEnumerable<Tuple<Type, Type>> handlers)
    {
        foreach (var handler in handlers)
        {
            registry.Register(handler.Item1, handler.Item2);
        }            
    }        
}

希望它也可以帮助其他人:)

干杯!