前言
前段时间经历了多轮面试,被几家公司问到了Ioc容器的相关知识,当初只是简略的回答了,其实在以前的项目中用到过,但不知道Ioc容器内部的运行原理或生命周期,以致于回答起来。。。。
今天我重新拾起,从零开始学起,记录自己学习的点滴,加深自己对Ioc容器理解。
什么是控制反转(IOC)、依赖注入(DI)
控制反转(Inversion of Control)简称IOC,是面向对象编程中的一种设计原则,可以用来降低对象之间的耦合度。Ioc容器把创建依赖对象的控制权交给了容器,由容器注入对象,而传统的都是在类的内部创建对象,从而导致类与类之间高耦合。
依赖注入(Dependency Injection)是组件之间依赖关系由容器在运行期决定。通俗的说,由容器动态的将某个依赖关系注入到组件之中。依赖注入的目的并非为软件带来更多功能,而是为了提升组件重用的频率,并为系统搭建一个灵活、可扩展的平台。
传统的方式
我们以数据库访问为例,一个是Sqlserver类,一个是Oracle类,当我们需要调用时可以选择哪种类型来访问数据库。
public interface IDataSource { ////// 获取数据库数据 /// string GetData(); } public class Sqlserver: IDataSource { public string GetData() { return "这里是SQLSERVER数据库,数据获取成功!"; } } public class Oracle : IDataSource { public string GetData() { return "这里是Oracle数据库,数据获取成功!"; } }
调用时
static void Main(string[] args) { IDataSource ds = new Sqlserver(); Console.WriteLine(ds.GetData()); Console.ReadLine(); }
然后我们进行代码改进,增加一个ManagerDB类,在构造函数中传入IDataSource实现对象, 就会自动创建对应的对象。
public class ManagerDB { public IDataSource _dataSource { get; set; } public ManagerDB(IDataSource dataSource) { _dataSource = dataSource; } public void DbList() { _dataSource.GetData(); } }
调用
ManagerDB managerDB = new ManagerDB(new Sqlserver()); managerDB.DbList();
Autofac构造函数注入
1. 在项目中通过NuGet程序包引入AutoFac。
2. 因本应用程序采用的是MVC,我们在Web项目下创建一个AutoFacManager类。
public class AutoFacManager { public static IContainer container { get; set; } public static void RegisterAutoFac() { var builder = new ContainerBuilder(); builder.RegisterType().As (); using (container = builder.Build()) { var user = container.Resolve (); user.GetData(); } } }
3.在Global文件中调用即可。
注入说明
1. builder.RegisterType
2. IContainer.Resolve(); 解析接口的实例也可理解为得到注入的实例。 如以下代码是得到Sqlserver的实例 public static void RegisterAutoFac() { var builder = new ContainerBuilder(); builder.RegisterType ().As (); using (container = builder.Build()) { var user = container.Resolve (); user.GetData(); } }
3. builder.RegisterType
4. IContainer.ResolveNamed(string name):解析某个接口的“命名实例”。例如上面的红色代码
5. builder.RegisterType
6. builder.RegisterType
7. IContainer.Resolve(NamedParameter namedParameter):在解析实例T时给其赋值,这个就是给你定义的方法的参数传值
修改:我们为ManagerDB构造函数加入Name参数 public class ManagerDB { public IDataSource _dataSource { get; set; } public string Name; public ManagerDB(IDataSource dataSource, string name) { _dataSource = dataSource; Name = name; } public string DbList() { return Name + ":" + _dataSource.GetData(); } } 调用: container.Resolve(new NamedParameter("name","刘先生"));
本篇到这已经完成了,有不对的地方,还希望各位能多多指点,共同学习进步。