• Autofac初探(一)


    前言

     前段时间经历了多轮面试,被几家公司问到了Ioc容器的相关知识,当初只是简略的回答了,其实在以前的项目中用到过,但不知道Ioc容器内部的运行原理或生命周期,以致于回答起来。。。。

    今天我重新拾起,从零开始学起,记录自己学习的点滴,加深自己对Ioc容器理解。

    什么是控制反转(IOC)、依赖注入(DI)

    控制反转(Inversion of  Control)简称IOC,是面向对象编程中的一种设计原则,可以用来降低对象之间的耦合度。Ioc容器把创建依赖对象的控制权交给了容器,由容器注入对象,而传统的都是在类的内部创建对象,从而导致类与类之间高耦合。

    依赖注入(Dependency Injection)是组件之间依赖关系由容器在运行期决定。通俗的说,由容器动态的将某个依赖关系注入到组件之中。依赖注入的目的并非为软件带来更多功能,而是为了提升组件重用的频率,并为系统搭建一个灵活、可扩展的平台。

    传统的方式

    我们以数据库访问为例,一个是Sqlserver类,一个是Oracle类,当我们需要调用时可以选择哪种类型来访问数据库。

     public interface IDataSource
        {
            /// <summary>
            /// 获取数据库数据
            /// </summary>
            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<Sqlserver>().As<IDataSource>();
    
                using (container = builder.Build())
                {
                    var user = container.Resolve<IDataSource>();
                    user.GetData();
                }
              
            }
        }
    

     3.在Global文件中调用即可。

    注入说明

    1.  builder.RegisterType<Object>().As<Iobject>(): 注入类型与实例,如上面代码中注入的是IDataSource接口与Sqlserver的实例
    2. IContainer.Resolve<T>(); 解析接口的实例也可理解为得到注入的实例。 如以下代码是得到Sqlserver的实例
       public static void RegisterAutoFac()
            {
                var builder = new ContainerBuilder();
                 
                builder.RegisterType<Sqlserver>().As<IDataSource>();
     
                using (container = builder.Build())
                {
                    var user = container.Resolve<IDataSource>();
                    user.GetData();
                }      
            }
    3. builder.RegisterType<Object>().Named<Iobject>(string name): 当一个接口注入不同的实例时,例如:IDataSource同时可注入Sqlserver与Oracle,为了区分多个实例我们可以取名来区分。
    
         public static void RegisterAutoFac()
            {
                var builder = new ContainerBuilder();
                builder.RegisterType<Sqlserver>().Named<IDataSource>("Sqlserver");
                builder.RegisterType<Oracle>().Named<IDataSource>("Oracle");
                using (container = builder.Build())
                {
                    var sqlserver = container.ResolveNamed<IDataSource>("Sqlserver");
                    sqlserver.GetData();
                    var oracle = container.ResolveNamed<IDataSource>("Oracle");
                    oracle.GetData();
                }
            }
    4. IContainer.ResolveNamed<IObject>(string name):解析某个接口的“命名实例”。例如上面的红色代码
    5. builder.RegisterType<Object>().InstancePerDependency():用于控制对象的生命周期,每次加载实例时都是新建一个实例,默认就是这种方式
    6. builder.RegisterType<Object>().SingleInstance():用于控制对象的生命周期,每次加载实例时都是返回同一个实例
    7. IContainer.Resolve<T>(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<ManagerDB>(new NamedParameter("name","刘先生"));

     本篇到这已经完成了,有不对的地方,还希望各位能多多指点,共同学习进步。

  • 相关阅读:
    github上fork的项目,如何同步原作者更新的内容?
    设计模式-简单工厂模式详解
    设计模式-建造者模式详解
    设计模式-原型模式详解
    设计模式-单例模式详解
    SqlServer断开所有连接
    Winform重写键盘按键事件
    从拖拉控件编程到面向设计编程(一)
    Springboot vue 前后分离 跨域 Activiti6 工作流 集成代码生成器 shiro权限
    java 微信自定义菜单 java微信接口开发 公众平台 SSM redis shiro 多数据源
  • 原文地址:https://www.cnblogs.com/liujie2272/p/12976715.html
Copyright © 2020-2023  润新知