Autofac 通过基于构造函数参数名称的约定来修饰查询处理程序



我们将IQueryHandler<TQUery,TResult>注入到MVC控制器中。我们在全球范围内将所有这些注册到容器中

我们编写了一个装饰器,可以缓存IQueryHandler的结果。

我们有时希望从同一个处理程序获取缓存的 reults,而有时则不这样做。

是否可以根据构造函数参数的名称有条件地获取修饰的处理程序。 例如注入IQueryHandler<UnemployedQuery, IEnumerable<People>> cachedPeopleHandler如果我们在构造函数参数名称前面加上缓存,我们实际上会用装饰器包装它?

只是尝试使用更多的约定而不是配置方法来简化事情。

是的,可以做到。下面是一个关于如何实现它的简单工作示例:

class Program
{
    public interface IQueryHandler{}
    private class QueryHandler : IQueryHandler
    {
    }
    private class CacheQueryHandler : IQueryHandler
    {
    }
    public interface IService
    {
    }
    private class Service : IService
    {
        private readonly IQueryHandler _queryHandler;
        private readonly IQueryHandler _cacheQueryHandler;
        public Service(IQueryHandler queryHandler, IQueryHandler cacheQueryHandler)
        {
            _queryHandler = queryHandler;
            _cacheQueryHandler = cacheQueryHandler;
        }
        public override string ToString()
        {
            return string.Format("_queryHandler is {0}; _cacheQueryHandler is {1}", _queryHandler,
                _cacheQueryHandler);
        }
    }
    static void Main(string[] args)
    {
        var builder = new ContainerBuilder();
        // Register the dependency
        builder.RegisterType<QueryHandler>().As<IQueryHandler>();
        // Register the decorator of the dependency
        builder.RegisterType<CacheQueryHandler>().Keyed<IQueryHandler>("cache");
        // Register the service implementation
        builder.RegisterType<Service>().AsSelf();
        // Register the interface of the service
        builder.Register(c =>
        {
            var ctor = typeof (Service).GetConstructors()[0];
            var parameters =
                ctor.GetParameters()
                    .Where(p => p.Name.StartsWith("cache"))
                    .Select(p => new NamedParameter(p.Name, c.ResolveKeyed("cache", p.ParameterType)));
            return c.Resolve<Service>(parameters);
        }).As<IService>();
        using (var container = builder.Build())
        {
            var service = container.Resolve<IService>();
            Console.WriteLine(service.ToString());
            Console.ReadKey();
        }
    }
}

更新:
基本上你需要:
1.想出一个总的惯例。在您的情况下,ctor参数名称的前缀"缓存"。
2. 像往常一样注册依赖项。
3. 注册您的装饰器,这样它们就不会覆盖您的原始依赖项,并且您可以根据约定轻松解决它们。例如键控、命名、通过属性等。
4. 注册使用装饰器的
类的实际实现5. 注册您的接口,该接口通过 lambda 表达式描述类,该表达式内部具有所有魔力。

注意:我只提供了一个简单而有效的示例。您可以使其美观,易于使用和快速,例如将其作为扩展,通用,缓存反射结果等。反正也不难。
谢谢。

最新更新