2016-12-15 2 views
0

является реализацией CQRS:Как зарегистрировать autofac декоратор для родового объекта для CQRS

public interface IQuery<TResult> {} 

public interface IQueryHandler<in TQuery, TResult> 
    where TQuery : IQuery<TResult> 
{ 
    Task<TResult> HandleAsync(TQuery query); 
} 

public interface IQueryDispatcher 
{ 
    Task<TResult> DispatchAsync<TQuery, TResult>(TQuery query) 
     where TQuery : IQuery<TResult>; 
} 

public class QueryDispatcher : IQueryDispatcher 
{ 
    private readonly IComponentContext resolver; 

    public QueryDispatcher(IComponentContext resolver) 
    { 
     if (resolver == null) 
     { 
      throw new ArgumentNullException(nameof(resolver)); 
     } 

     this.resolver = resolver; 
    } 

    public async Task<TResult> DispatchAsync<TQuery, TResult>(TQuery query) 
     where TQuery : IQuery<TResult> 
    { 
     if (query == null) 
     { 
      throw new ArgumentNullException(nameof(query)); 
     } 

     var handler = resolver.Resolve<IQueryHandler<TQuery, TResult>>(); 
     return await handler.HandleAsync(query); 
    } 
} 

И я хочу, чтобы создать общий запрос:

public class GetEntitiesQuery<TEntity> : IQuery<IQueryable<TEntity>> 
    where TEntity : Entity 
{ 
} 

public class GetEntitiesQueryHandler<TEntity> : IQueryHandler<GetEntitiesQuery<TEntity>, IQueryable<TEntity>> 
    where TEntity : Entity 
{ 
    // this code ... 
} 

Я пытаюсь зарегистрироваться общий класс следующим образом:

  builder.RegisterType<QueryDispatcher>().As<IQueryDispatcher>().InstancePerLifetimeScope(); 

     builder.RegisterAssemblyTypes(assemblies) 
      .As(type => type.GetInterfaces() 
       .Where(interfaceType => interfaceType.IsClosedTypeOf(typeof(IQueryHandler<,>))) 
       .Select(interfaceType => new KeyedService("QueryHandler", interfaceType))) 
      .InstancePerLifetimeScope(); 

И бросить ошибка IQueryHandler не была зарегистрирована

Возможно ли это с помощью Autofac?

ответ

0

много общего с Issue registering generic types with Autofac in ASP.NET Core

Там нет декораторы в коде вы показываете.

Ошибка, которую вы получаете, ожидается при регистрации ваших обработчиков на keying их - с классом KeyedService. Если вы хотите, чтобы ваш код работал, у вас есть 2 решения.

Лучшим вариантом является не предоставление ключевых услуг, так как нет причин - опять же, только глядя на код, который вы включили, - чтобы указать ваши услуги. Вы можете зарегистрировать их без манипуляция их таким образом:

builder 
    .RegisterAssemblyTypes(assemblies) 
    .AsClosedTypesOf(typeof(IQueryHandler<,>)) 
    .InstancePerLifetimeScope(); 

Другой вариант будет инструктировать Autofac вы ищете сервис ключом когда вы разрешить IQueryHandler<TQuery, TResult> с того, как вы зарегистрировали их. Чтобы сделать это, вы должны изменить свой QueryDispatcher код:

var handler = resolver.ResolveKeyed<IQueryHandler<TQuery, TResult>>("QueryHandler"); 

Пожалуйста, не ключ передается методу ResolveKeyed соответствует той, которая используется в коде регистрации. Я не знаю, почему вы выбрали второй вариант, но это возможно.

Я предполагаю, что вы немного смущены decorators. Использование их требует от вас ключевых услуг, чтобы вы могли украсить услуги, которые были keyed. Пожалуйста, посмотрите еще на the relevant documentation.

Редактировать после комментария Edwok в

Для родового GetEntitiesQueryHandler<TEntity> случае, я бы сказал, что вы должны зарегистрировать его в качестве open-generic component:

builder 
    .RegisterGeneric(typeof(GenericEntitiesQueryHandler<>)) 
    .As(typeof(IQueryHandler<,>)); 
+0

Не работают оба решения. Может быть, GetEntitiesQueryHandler и GetEntitiesQuery «полузакрытый» общий компонент, попытался зарегистрировать декораторы, не работал. – Edwok

+0

http://stackoverflow.com/questions/27509729/registering-half-closed-generic-component – Edwok

+0

Как с Autofac? – Edwok

Смежные вопросы