IOC之Autofac

本文介绍了在研究Nopcommerce时发现的IOC框架Autofac,强调了其低侵入性和优秀性能。通过示例展示了Autofac的构造函数注入,并探讨了为何不推荐属性注入。此外,还讲解了如何利用Autofac替代MVC中的DefaultDependencyResolver,以实现更高级别的依赖注入控制。
摘要由CSDN通过智能技术生成

最近在研究Nopcommerce,发现其内部IOC框架使用了autofac,简单的了解了一下,记录一下简单的一些用法。初浅了解下来,有一个很直观的感受,就是对代码几乎没什么侵入性,其他性能之类没有测试,但据说性能极佳。


1. 构造函数注入,如下示例(后面所有说明都是在以下的示例基础上进行的)

public interface IRepository
    {
        void Update();
    }
    public class FirstRepository : IRepository
    {
        public void Update()
        {
            Console.WriteLine("FirstRepository.Update");
        }
    }
    public class SecondRepository : IRepository
    {
        public void Update()
        {
            Console.WriteLine("SecondRepository.Update");
        }
    }

    public class ConcreteController
    {
        private IRepository _repository;
        public ConcreteController(IRepository repository)
        {
            _repository = repository;
        }

        public void Update()
        {
            _repository.Update();
        }
    }
调用如下:

            ContainerBuilder builder = new ContainerBuilder();
            builder.RegisterType<ConcreteController>().AsSelf();//也可直接写成builder.RegisterType<ConcreteController>()
            builder.RegisterType<FirstRepository>().As<IRepository>();//注册FirstRepository为IRespository默认实现
            IContainer container = builder.Build();
            //默认以类参数最多的构造方法进行构造,构造参数根据类型从注册列表中寻找注册的实现类,此处获取的是FirstRepository
            ConcreteController controller = container.Resolve<ConcreteController>();
            controller.Update();//FirstRepository.Update
对同一接口多次注册时,会以最后一次注册的实现类为默认实现类,如下:

            ContainerBuilder builder = new ContainerBuilder();
            builder.RegisterType<ConcreteController>().AsSelf();//也可直接写成builder.RegisterType<ConcreteController>()
            builder.RegisterType<FirstRepository>().As<IRepository>();
            builder.RegisterType<SecondRepository>().As<IRepository>();//IRepository的默认实现类为SecondRepository
            IContainer container = builder.Build();
            ConcreteController controller = container.Resolve<ConcreteController>();
            controller.Update();//SecondRepository.Update
如果有这样的一个需求:如果前面注册过了接口的实现类,则以之前注册过的实现类为默认值,如果没有注册过则以此次注册的实现类为默认值,可以通过以下方式实现:

            //如果之前存在默认值则以之前注册的值为默认值,否则以此次注册的实现类为默认值
            builder.RegisterType<SecondRepository>().As<IRepository>().PreserveExistingDefaults();
            ...
            controller.Update();//FirstRepository.Update
在注册时,可以通过委托的方式,预先指定一个接口的实现类。即采用ContainerBuilder.Register<T>(委托)的方式来进行实现,如下:

            ContainerBuilder builder = new ContainerBuilder();
            //通过Register方法,预先指定一个获取实现的委托来注册接口的实现类
            builder.Register<IRepository>(r => new FirstRepository());
            IContainer container = builder.Build();
            IRepository repository = container.Resolve<IRepository>();//FirstRepository
            repository.Update();//FirstRepository.Update
autofac构造注入时,在通过无参的IContainer.resolver获取实现类时,会默认通过实现类最多的参数进行构造,构造方法的参数值为该参数类型注册的实现类。如果该参数值的Type没有在autofac进行注册,则直接报错,如下:

            ContainerBuilder builder = new ContainerBuilder();
            builder.RegisterType<ConcreteController>();
            IContainer container = builder.Build();
            //ConcreteController的构造方法中需要一个IRepository参数,但autofac检索不到IRepository的实现类,注入失败,报错
            //此处不光是针对参数值是引用类型,对于值类型同样存在这样的问题,例如把参数换成int i,同样注入失败,报错
            ConcreteController controller = container.Resolve<ConcreteController>();//error
对于这样的问题,可以通过在Resolve 时,自行装配,如下:
            ContainerBuilder builder = new ContainerBuilder();
            builder.RegisterType<ConcreteController>();
            IContainer container = builder.Build();
            //之前没有对ConcreteController构造方法中的参数repository类型IRepository进行注册,但可在解析提取时自动注入
   
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值