#c# #dependency-injection #decorator #autofac
#c# #внедрение зависимостей #декоратор #autofac
Вопрос:
Используя шаблон CQS, у меня есть запрос, подобный этому:
public class MyQuery : IQuery<View<SingleView>>
{
public string Token { get; set; }
public Criteria Criteria { get; set; }
}
public class MyQueryHandler : IQueryHandler<MyQuery, View<SingleView>>
{
private readonly IProductRepository _productRepository;
public MyQueryHandler(IProductRepository productRepository)
{
_productRepository = productRepository;
}
public View<SingleView> Handle(MyQuery query)
{
var data = // get my data
return data;
}
}
Конечно, у меня есть много запросов и соответствующих им обработчиков запросов. Теперь у меня ситуация, когда я хочу украсить только MyQueryHandler
. Я не хочу украшать остальные запросы.
Я использую Autofac, но я просто не могу заставить его работать.
Вот как регистрируются запросы:
builder.RegisterAssemblyTypes(assemblies)
.As(type => type.GetInterfaces()
.Where(interfaceType => interfaceType.IsClosedTypeOf(typeof(IQueryHandler<,>)))
.Select(interfaceType => new KeyedService("queryHandler", interfaceType)));
// Register query decorators
builder.RegisterGenericDecorator(
typeof(LogQueryDecorator<,>),
typeof(IQueryHandler<,>),
"queryHandler");
И вот декоратор, который я хочу использовать для MyQueryHandler
:
public class SaveMyQueryData : IQueryHandler<MyQuery, View<SingleView>>
{
private readonly IQueryHandler<MyQuery, View<SingleView>> _queryHandler;
private readonly IProductRepository _productRepository;
public SaveMyQueryData(
IQueryHandler<MyQuery, View<SingleView>> queryHandler,
IProductRepository productRepository)
{
_queryHandler = queryHandler;
_productRepository = productRepository;
}
public View<SingleView> Handle(MyQuery query)
{
var result = _queryHandler.Handle(query);
// do something with result
return resu<
}
}
Итак, как я могу зарегистрироваться SaveMyQueryData
в качестве декоратора только для MyQueryHandler
использования Autofac?
Ответ №1:
Наконец-то у меня все работает так, как я хочу. Вот мое решение:
Сделайте декоратор открытым вместо закрытого типа:
public class SaveMyQueryData : IQueryHandler<Q, R>
{
private readonly IQueryHandler<Q, R> _queryHandler;
private readonly IProductRepository _productRepository;
public SaveMyQueryData(
IQueryHandler<Q, R> queryHandler,
IProductRepository productRepository)
{
_queryHandler = queryHandler;
_productRepository = productRepository;
}
public Q Handle(Q query)
{
var result = _queryHandler.Handle(query);
var view = result as View<SingleView>;
// do something with view
return resu<
}
}
Затем при регистрации типа с помощью Autofac сделайте это:
builder.RegisterGenericDecorator(
typeof(SaveMyQueryData<,>),
typeof(IQueryHandler<,>),
context => context.ImplementationType == typeof(MyQueryHandler));
Последняя строка содержит магию. С помощью третьего параметра RegisterGenericDecorator
вы можете указать условие, при котором следует применять декоратор. Это новое начиная с Autofac 4.9, и это решило мою проблему.