Generics LightInject注册泛型查询处理程序

Generics LightInject注册泛型查询处理程序,generics,dependencies,registration,code-injection,Generics,Dependencies,Registration,Code Injection,我对CQRS模式非常陌生,在将所有这些与我选择的依赖注入容器结合起来时遇到了问题 我拥有的是一个通用查询对象 public interface IQuery<TResult> { } 公共接口iquiry { } 它由GenericQuery实现 public class GenericQuery<TSrcEntity> : IQuery<IEnumerable<TSrcEntity>> { public Expression<F

我对CQRS模式非常陌生,在将所有这些与我选择的依赖注入容器结合起来时遇到了问题

我拥有的是一个通用查询对象

public interface IQuery<TResult>
{
}
公共接口iquiry
{
}
它由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; }
}
公共类泛型查询:IQuery
{
公共表达式筛选器{get;set;}
公共Func OrderBy{get;set;}
公共IEnumerable IncludeProperty{get;set;}
}
然后,我通过查询分派器来处理所有这些,查询分派器通过依赖项解析器确定要使用哪个处理程序

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);
    }
}
公共类QueryDispatcher:IQueryDispatcher
{
公共TResult调度(TQuery查询),其中TQuery:IQuery
{
var handler=DependencyResolver.Get();
返回处理程序.检索(查询);
}
}
处理程序实现

 public class GenericQueryHandler<TSrcEntity> : IQueryHandler<GenericQuery<TSrcEntity>, IEnumerable<TSrcEntity>> where TSrcEntity : class
{
    public IEnumerable<TSrcEntity> Retreive(GenericQuery<TSrcEntity> query)
    {
        return GetDocuments();
    }
公共类GenericQueryHandler:IQueryHandler其中TSrcEntity:class
{
公共IEnumerable检索(GenericQuery查询)
{
返回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();

    }
类程序
{
静态void Main(字符串[]参数)
{
var container=新的ServiceContainer();
//服务
container.Register();
//质疑
Register(typeof(IQuery),typeof(GenericQuery));
//处理程序这一个工作,但我不想登记的一切明确。
容器寄存器(typeof(IQueryHandler),typeof(GenericQueryHandler));
//调度员
container.Register();
DependencyResolver.SetResolver(容器);
var service=container.GetInstance();
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>));
//这一个有效,但我不想明确地注册所有内容。
容器寄存器(typeof(IQueryHandler),typeof(GenericQueryHandler));
但我不想对每个实体都这样做。更熟悉LightInject的人能帮我吗

可以在以下位置找到示例程序:


谢谢

我知道这是一篇老文章,但我也遇到了同样的问题,我找到了解决办法。我在这里找到了解决办法:

该页上的代码如下:

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);
        }            
    }        
}
公共静态类ContainerExtensions
{
公共静态无效注册表CommandHandlers(此IServiceRegistry serviceRegistry)
{
var命令类型=
Assembly.GetCallingAssembly()
.GetTypes()
.Select(t=>GetGenericInterface(t,typeof(ICommandHandler)))
。其中(m=>m!=null);
RegisterHandler(serviceRegistry、CommandType);
Register(factory=>newcommandexecutor((IServiceFactory)serviceRegistry));
decoration(typeof(ICommandHandler),typeof(TransactionalCommandDecorator));
}
公共静态无效注册表QueryHandler(此IServiceRegistry服务注册表)
{
var命令类型=
Assembly.GetCallingAssembly()
.GetTypes()
.Select(t=>GetGenericInterface(t,typeof(IQueryHandler)))
。其中(m=>m!=null);
RegisterHandler(serviceRegistry、CommandType);
Register(工厂=>newQueryExecutor((IServiceFactory)serviceRegistry));
decoration(typeof(IQueryHandler)、typeof(QueryHandlerLogDecorator));
}
私有静态元组GetGenericInterface(类型类型,类型genericTypeDefinition)
{           
var closedGenericInterface=
type.GetInterfaces()
.SingleOrDefault(i=>i.IsGenericType&&i.GetGenericTypeDefinition()==genericTypeDefinition);
if(closedGenericInterface!=null)
{
var constructor=type.GetConstructors().FirstOrDefault();
if(构造函数!=null)
{
var isDecorator=constructor.GetParameters().Select(p=>p.ParameterType).Contains(closedGenericInterface);
如果(!isDecorator)
{
返回Tuple.Create(closedGenericInterface,type);
}
}                
}
返回null;
}
私有静态无效注册表句柄(IServiceRegistry注册表,IEnumerable句柄)
{
foreach(处理程序中的变量处理程序)
{
Register(handler.Item1,handler.Item2);
}            
}        
}
希望它也能帮助别人:)


干杯!

假设LINQ本身为任何过滤器映射减少需求提供了足够的抽象,那么我认为您额外的抽象似乎是不必要的复杂性。此外,我将删除您问题中的任何CQRS引用,因为它纯粹是关于在您的容器中注册泛型的。谢谢Alexey。我对帖子做了一些更改。您你说得对,注册泛型比注册CQR更重要。@SimonFine你找到解决办法了吗?我面临着确切的问题。