Как украсить один конкретный тип с помощью Autofac?

#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, и это решило мою проблему.