【AutoFac】依赖注入和控制反转的使用

在开始之前首先解释一下我认为的依赖注入和控制反转的意思。(新手理解,哪里说得不正确还请指正和见谅)

控制反转:我们向IOC容器发出获取一个对象实例的一个请求,IOC容器便把这个对象实例“注入”到我们的手中,在这个时候我们不是一个创建者,我们是以一个请求者的身份去请求容器给我们这个对象实例。我们所有的对象依赖于容器提供给你的资源,控制权落到了容器身上。在这里的身份转化或许就是控制反转的核心吧。 

依赖注入:我们向容器发出请求以后,获得这个对象实例的过程就叫依赖注入。也就是我们在使用对向前我们都需要先注入也就是这个意思吧。

今天学习了下AutoFac依赖注入这个插件,然后还有以前用过的Unity这个插件简单做个笔记整理。首先我分两个部分记录,第一部分一点有点的记录今天学习的AutoFac这个插件,最后一部分直接补上以前使用Unity插件的代码封装不做详细解释。

AutoFac入门

还是放上官网给出的整合流程吧;

  • 按照 控制反转 (IoC) 的思想构建你的应用.
  • 添加Autofac引用.
  • 在应用的 startup 处...
  • 创建 ContainerBuilder.
  • 注册组件.
  • 创建容器,将其保存以备后续使用.
  • 应用执行阶段...
  • 从容器中创建一个生命周期.
  • 在此生命周期作用域内解析组件实例.

创建简单的例子

通过一个控制台简单清晰的介绍了如何使用AutoFac这个插件。

创建项目

创建一个控制台程序叫AutoFacDome。

这里就不做过多解释了,大家都会创建哈哈。

引用Autofac

使用我vs强大的nuget来进行添加引用:

直接在搜索栏输入Autofac直接就可以查找出来:

Nuget命令行:

Install-Package Autofac -Version 4.8.1

创建一个依赖关系类:

首先我们定义一个服务接口=>IService

    /// <summary>
    /// 服务接口
    /// 描述:为了方法的继承和扩展更好的演示下面的例子
    /// </summary>

    public interface IService
    {
        //定义一个输出方法
        void PrintWord();
    }

然后我们在创建一个服务类去实现接口(IService)=>Service

/// <summary>
    /// 服务类具体实现
    /// </summary>
    public class Service : IService
    {
        //输出方法的实现
        public void PrintWord()
        {
            Console.WriteLine("我是service打印的Hello word");
        }
    }

好了现在我们有了一个服务接口和一个服务类 ,并且类下面实现了输出会打印:我是service打印的Hello word。常规我们想调用这个方法我们都是在mian函数中示例化该类进行调用,类似于这样

            IService service = new Service();
            service.PrintWord();
            //或者
            Service service2 = new Service();
            service2.PrintWord();

但是今天我们说的不是这些我们说的另外的方式。那我们看看 autofac是怎么调用的。

注册容器

其实万变不离其宗,不管是autofac,unity,spring.net等,其实都是这么一个套路就是先注册容器然后才能从容器取出,其实这个也非常好理解容器本身是没有东西的,你想用东西就要提前放进去,只有容器有了你请求才会给你。不同的插件只不过是各自的封装方法或者形式存在着差异。autofac的注册方式:

           // 创建容器
            var builder = new ContainerBuilder();
            //注册对象
            builder.RegisterType<Service>().As<IService>();
            Container = builder.Build();

这个时候我们就相当于把service类放入了容器,这样在后面你才可以取出来使用。

使用容器

这里我写了两个使用的方法根据不同情况使用把:

            //使用方法一
            using (var ioc = Container.BeginLifetimeScope())
            {
                var service = ioc.Resolve<IService>();
                service.PrintWord();
            }

            //使用方法二
            //var service = Container.Resolve<IService>();
            //service.PrintWord();

运行

我们可以任意注释一个方法来检测一下结果:

这样我们就完成了autofac的简单运用。

AutoFac新手村

通过上面的例子我们已经知道autofac的基本运用。基本运用还不行我们还要知道一些知识。

多构造函数

第一种:就是单纯的有多个构造

如果我们同一个类存在多个构造函数会给我们一个什么结果哪这个在有时候是非常重要的。

所以我们修改我们的service类:

 /// <summary>
    /// 服务类具体实现
    /// </summary>
    public class Service : IService
    {
        //默认构造
        public Service() {
            Console.WriteLine("我是service的默认构造");
        }
        //一个参数的构造
        public Service(int a)
        {
            Console.WriteLine("我是service的一个参数构造");
        }
        //两个参数的构造
        public Service(int a,int b)
        {
            Console.WriteLine("我是service的两个参数构造");
        }
        //输出方法的实现
        public void PrintWord()
        {
            Console.WriteLine("我是service打印的Hello word");
        }
    }

其他都不变运行代码:

这里就是执行了默认构造,所有在一个类有多个构造情况下默认的形式是返回给我们默认构造函数的类实例。

第二种:多构造参数类型并且参数类型也注册容器

这个什么意思哪就是说有两个类,其中一个类的构造函数参数是另一个类。并且参数类型也进行注册容器

我们增加一个ServiceTwo类:

 public class ServiceTwo :IService
    {
        //输出方法的实现
        public void PrintWord()
        {
            Console.WriteLine("我是serviceTwo打印的Hello word");
        }
    }

修改service类中的一个参数构造为:

        //一个参数的构造
        public Service(ServiceTwo two)
        {
            Console.WriteLine("我是service的一个参数构造");
        }

main函数增加注册:

            //注册对象
            builder.RegisterType<Service>().As<IService>();
            builder.RegisterType<ServiceTwo>();
            Container = builder.Build();

然后运行:

这里就和上面的结果不一样了,所有在使用时需要注意,autofac官方解释为:当使用基于反射的组件时, Autofac 自动为你的类从容器中寻找匹配拥有最多参数的构造方法。

说白了就是如果使用注册类并且注册类多构造函数,并且其构造参数为其他注册类时候,查找的构造函数包含注册类最多的构造函数返回。

指定构造函数

由容器掌握我们的构造函数总是不好的,所有我们要自己指定想创建谁创建谁=>UsingConstructor(参数类型)可以多个

在这里需要注意我们既然指定了构造函数就要为构造函数传参不然会抱错,参数可以是注册时候传也可以解析时候传,我写了一个解析时候传的:

            // 创建容器
            var builder = new ContainerBuilder();
            //注册对象
            builder.RegisterType<Service>().As<IService>().UsingConstructor(typeof(int), typeof(int));
           // builder.RegisterType<ServiceTwo>();
            Container = builder.Build();

            //使用方法一
            using (var ioc= Container.BeginLifetimeScope())
            {
                var service = ioc.Resolve<IService>(new NamedParameter("a", 1), new NamedParameter("b", 1));
                service.PrintWord();
            }

运行结果:

类的覆盖

如果我两个类或者多个类同时实现一个接口并且注册的时候都与接口做了关联。

那么会存在覆盖现象。

下面我们把main函数改造让serviceTwo也注册与IService关联

            // 创建容器
            var builder = new ContainerBuilder();
            //注册对象
            builder.RegisterType<Service>().As<IService>();
            builder.RegisterType<ServiceTwo>().As<IService>();
            Container = builder.Build();

            //使用方法一
            using (var ioc = Container.BeginLifetimeScope())
            {
                var service = ioc.Resolve<IService>();
                service.PrintWord();
            }

运行结果:

这个时候我们得到的是serviceTwo类的示例。如果改变Service和ServiceTwo的位置就会返回service实例。

属性注入

WithProperty:绑定一个属性和他的值

我们给ServiceTwo类添加name属性并扩展一个打印方法:

 public string name { get; set; }

        public void PrintName()
        {
            Console.WriteLine($"name属性:{name}");
        }

然后main函数改为

            builder.RegisterType<Service>().As<IService>();
            builder.RegisterType<ServiceTwo>().WithProperty("name", "张三");
            Container = builder.Build();

            //使用方法一
            using (var ioc = Container.BeginLifetimeScope())
            {
                var service = ioc.Resolve<ServiceTwo>();
                service.PrintName();
            }

运行结果:

方法注入

OnActivating:方法注入

我们在ServiceTwo类添加设置名称方法

  public void setName()
        {
            name = "李四";
        }

然后main函数改为:

builder.RegisterType<ServiceTwo>().OnActivating(e=> {
                e.Instance.setName();
            });

运行结果:

AutoFac集成-MVC

首先创建mvc项目就不过多解释了。

引用dll:

这里需要引用两个dll文件: Autofac.Mvc5和 Autofac。注意这里我的是mvc5所以我安装的Autofac.Mvc5 这个要根据mvc版本做对应不然会报错。

通过nuget安装就可以了。

相关类

还是我们的Service类和IService类来做示例演示:

    /// <summary>
    /// 服务接口
    /// 描述:为了方法的继承和扩展更好的演示下面的例子
    /// </summary>

    public interface IService
    {
        //定义一个输出方法
        void PrintWord();
    }

    /// <summary>
    /// 服务类具体实现
    /// </summary>
    public class Service : IService
    {
        //默认构造
        public Service()
        {
            Console.WriteLine("我是service的默认构造");
        }
        //输出方法的实现
        public void PrintWord()
        {
            System.Diagnostics.Debug.WriteLine("调起了service中的方法");
        }
    }

配置文件

配置Global文件,来注入控制器。下面我只做构造函数注入和属性注入

protected void Application_Start()
        {

            var builder = new ContainerBuilder();

            // 通过程序集注册所有控制器和属性注入
            //builder.RegisterControllers(typeof(MvcApplication).Assembly);
            builder.RegisterControllers(Assembly.GetExecutingAssembly()).PropertiesAutowired();

            builder.RegisterType<Service>().As<IService>();
            // 将依赖性分解器设置为AutoFac。
            var container = builder.Build();
            DependencyResolver.SetResolver(new AutofacDependencyResolver(container));

            AreaRegistration.RegisterAllAreas();
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);
        }

控制器如何使用:

打开home控制器:

  public class HomeController : Controller
    {

        /// <summary>
        /// 构造函数注入
        /// </summary>
        /// <param name="serviceClient"></param>
        public HomeController(IService serviceClient)
        {
            this.Service = serviceClient;
        }
        public IService Service;

        /// <summary>
        /// 属性注入
        /// </summary>
        /// <returns></returns>
       // public IService Service2 { get;  set; }
        public ActionResult Index()
        {
            //使用方法一
            Service.PrintWord();
            //Service2.PrintWord();

            return View();
        }

    }

运行看效果:

原文地址:https://www.cnblogs.com/yanbigfeg/p/9855960.html

时间: 2024-08-05 16:36:39

【AutoFac】依赖注入和控制反转的使用的相关文章

浅谈依赖注入与控制反转

前言:设计模式其实是一个很空洞的东西,设计模式有几十种,有些人觉得工厂模式也单例模式已经足够解决大部分问题.而有些人觉得任何设计模式都会让开发变得更“复杂”,更“低效”.所以千万不要太过追求他的实际意义和作用,否则你已经坠入云雾.但是不管怎么样,实际工作中还是要对它们有所了解,下面从php的角度来讲一下依赖注入.控制反转.反射等概念.如有错误之处,还望路过大神多加指点 首先设定场景,假如一个类需要数据库连接,最简单的做法可能是: class example { private $_db; fun

谈谈php依赖注入和控制反转

要想理解php依赖注入和控制反转两个概念,就必须搞清楚如下的问题: DI--Dependency Injection   依赖注入 IoC--Inversion of Control  控制反转 1.参与者都有谁? 答:一般有三方参与者,一个是某个对象:一个是IoC/DI的容器:另一个是某个对象的外部资源.又要名词解释一下,某个对象指的就是任意的.普通的Java对象; IoC/DI的容器简单点说就是指用来实现IoC/DI功能的一个框架程序:对象的外部资源指的就是对象需要的,但是是从对象外部获取的

Spring 的核心机制:依赖注入(控制反转)

一.说到依赖注入(控制反转),先要理解什么是依赖. Spring 把相互协作的关系称为依赖关系.假如 A 组件调用了 B 组件的方法,我们可称A 组件依赖于 B 组件. 二.什么是依赖注入. 在传统的程序设计过程中,通常由调用者来创建被调用者的实例. 在依赖注入的模式下,创建被调用者的工作不再由调用者来完成,因此称为控制反转:创建被调用者实例的工作通常由Spring 容器来完成,然后注入给调用者,因此也称为依赖注入. 三.依赖注入的好处. 依赖注入让 Spring 的 Bean 以被指文件组织在

php之依赖注入和控制反转

  DI——Dependency Injection   依赖注入  IoC——Inversion of Control  控制反转  要想理解上面两个概念,就必须搞清楚如下的问题: 1.参与者都有谁? 答:一般有三方参与者,一个是某个对象:一个是IoC/DI的容器:另一个是某个对象的外部资源.又要名词解释一下,某个对象指的就是任意的.普通的Java对象; IoC/DI的容器简单点说就是指用来实现IoC/DI功能的一个框架程序:对象的外部资源指的就是对象需要的,但是是从对象外部获取的,都统称资源

反射机制、依赖注入、控制反转

反射机制 正向: 代码->dll, 先编码, 定义好类,通过实例化对象来调用之. 反向: dll->类[方法,属性]. 从已经有的dll文件反编译得到其中的一些可用的方法. 审查元数据并收集关于它的类型信息的能力.元数据(编译以后的最基本数据单元)就是一大堆的表,当编译程序集或者模块时,编译器会创建一个类定义表,一个字段定义表,和一个方法定义表等. System.reflection命名空间包含的几个类,允许你反射(解析)这些元数据表的代码. 反射是.Net中获取 运行时类型信息的方式,.Ne

Java的依赖注入(控制反转)

两个主角"依赖注入"和"控制反转": 1.二都说的都是同一件事,只是叫法不同.是一个重要的面向对象编程的法则,也是一种设计模式: 2.英文原称:依赖注入,Dependency Injection(DI); 控制反转,Inversion of Control(IoC). 3.作用:削减计算机程序的耦合问题: 4.为什么叫"控制反转":创建被调用者的工作不再由调用者来完成,因此称为控制反转.结合Java说,当某个Java实例需要其他Java实例时,系

(转)依赖注入和控制反转

发现一篇介绍依赖注入和控制反转的文章,特转载以备后用. 文章地址1:http://baitai.iteye.com/blog/792980 相关文章:http://www.cnblogs.com/DebugLZQ/archive/2013/06/05/3107957.html: http://www.cnblogs.com/xingyukun/archive/2007/10/20/931331.html: http://www.cnblogs.com/zhenyulu/articles/6417

简单解析依赖注入(控制反转)在Spring中的应用

IoC——Inversion of Control  控制反转DI——Dependency Injection   依赖注入 大家都知道,依赖注入是Spring中非常重要的一种设计模式.可能很多初学者对这种看起来高深的东西有一种抗拒,这里就 简单介绍一下到底什么是依赖注入,Spring到底又到底是如何运用依赖注入的. 依赖关系:在A组件中要引用B组件的对象,则称A依赖于B依赖关系会造成各组件之间的硬编码,为解决依赖关系,一般的解决方法如下: 1.A组件先创建B组件,在调用B组件方法2.A组件先通

PHP 依赖注入和控制反转再谈(二)

今天有个朋友看到yii2中介绍的依赖注入一头雾水,之前我写过类似的文章发给他看了,可能还没深入理解吧,这里我再通俗点描述下依赖注入的原理吧,尽可能滴说通俗易懂一点吧:先还是扯下概念性滴问题(概念问题我个人的原则总是先简单瞟一眼概念,通过实例来对概念加深理解了) 要想理解 PHP 依赖注入 和 控制反转 两个概念,我们还是必须搞清楚下面的两个问题: DI -- Dependency Injection 依赖注入 IoC -- Inversion of Control 控制反转 什么是依赖注入 没有