我对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更熟悉的人可以帮忙吗?
找到示例程序由于
答案 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);
}
}
}
希望它也可以帮助其他人:)
干杯!