【Autofac笔记】一个服务多个实现

当一个服务注册多个实现时,如何区分?如果我们一个服务只有一个实现类,直接使用As()即可,但是如果一个服务有多个实现类,如何获取实现类

获取全部实现类

解析时直接使用IEnumerable<服务类型>类型的参数,如下
注册:

builder.RegisterType<Cat>().As<IAnimal>();
builder.RegisterType<Dog>().As<IAnimal>();
builder.RegisterType<Panda>().As<IAnimal>();

解析:

public IActionResult Index([FromServices] IEnumerable<IAnimal> animals)
        {
            return View();
        }

获取指定实现类

在注册时进一步按键标识,解析时使用键解析。键可以时一个名字、枚举、Type...
被注入的类在注册时要调用WithAttributeFiltering()
注册:

builder.RegisterType<AnimalHome>().WithAttributeFiltering();

builder.RegisterType<Cat>().Keyed<IAnimal>("cat");//按名称
builder.RegisterType<Dog>().Keyed<IAnimal>("dog");
builder.RegisterType<Panda>().Keyed<IAnimal>(typeof(Panda));//按Type

构造函数注入:

public AnimalHome([KeyFilter("dog")] IAnimal animals)
        {
        }

IIndex索引注入

解析组件可以使用IIndex<K,V>作为参数的构造函数从基于键的服务中选择需要的实现。
它的好处是动态的选择需要解析的服务,而不是在构造函数中就决定使用哪个键
注册:

builder.RegisterType<AnimalFactory>();

解析:

public class AnimalFactory
{
    private readonly IIndex<Type, IAnimal> _lookup = null;
    public AnimalFactory(IIndex<Type, IAnimal> lookup)
    {
        this._lookup = lookup;
    }
    public IAnimal Create(Type handlerType)
    {
        return this._lookup[handlerType];
    }
}

扩展KeyFilter

[KeyFilter]是通过继承ParameterFilterAttribute来实现功能,我们可以自己写一个类继承ParameterFilterAttribute,可以更灵活解析:

    public sealed class DependencyDBAttribute : ParameterFilterAttribute
    {
        public DependencyDBAttribute(string serviceKey, bool readOnly)
        {
            this.ServiceKey = serviceKey;
            this.ReadOnly = readOnly;
        }

        public string ServiceKey { get; }
        public bool ReadOnly { get; set; }

        public override object ResolveParameter(ParameterInfo parameter, IComponentContext context)
        {
            if (string.IsNullOrWhiteSpace(this.ServiceKey))
                return this.ReadOnly
                    ? context.ResolveKeyed("_slave", parameter.ParameterType, new NamedParameter("readOnly", true))
                    : context.Resolve(parameter.ParameterType);

            return this.ReadOnly
                ? context.ResolveKeyed($"{this.ServiceKey}_slave", parameter.ParameterType, new NamedParameter("readOnly", true))
                : context.ResolveKeyed(this.ServiceKey, parameter.ParameterType);

        }
    }

注入:

    public class CommonService
    {
        public CommonService([DependencyDBAttribute("master", true)]IDB db)
        {
        }
    }
posted @ 2019-12-26 09:04  .Neterr  阅读(785)  评论(1编辑  收藏  举报