• IOC容器之Autofac


    符合IOC理念的容器可以自己进行设计,也可以使用第三方的,符合IOC理念的容器也有不少,有的还提供了源码。Autofac是一种IOC的实现,这篇文章对Autofac做个简单的介绍,毕竟Autofac官方文档介绍的很详细。

    先简单说一下IOC和DI:

    IOC:是一种设计理念,调用者不再创建类的实例对象,而是交给容器,这就是控制反转

    DI:容器创建好类对象再注入调用者的过程,就是依赖注入,通常有属性注入、构造函数注入等方式

    总结来说,IoC是一种很宽泛的理念,DI是实现了IoC的其中一种方法

    接下来将通过一个demo来使用Autofac

    构建MVC应用

     

    一、先构建出符合IOC思想的应用,关系图如下:

    1、先构建AutoFac.Modle

    using System;
    namespace AutoFacDemo.AutoFac.Modle
    {
        public class UserModel
        {
            public string Id { get; set; }
            public string UserName { get; set; }
        }
    }

    2、构建AutoFac.IRepository和AutoFac.Repository

    using AutoFacDemo.AutoFac.Modle;
    
    namespace AutoFacDemo.AutoFac.IRepository
    {
        public interface IUserRepository
        {
            void AddUser(UserModel userModel);
        }
    }
    using AutoFacDemo.AutoFac.IRepository;
    using AutoFacDemo.AutoFac.Modle;
    
    namespace AutoFacDemo.AutoFac.Repository
    {
        public class UserRepository:IUserRepository
        {
            public void AddUser(UserModel userModel)
            {
               //do something
            }
        }
    }

    3、构建AutoFac.IService和AutoFac.Service

    using AutoFacDemo.AutoFac.Modle;
    
    namespace AutoFacDemo.AutoFac.IService
    {
        public interface IUserService
        {
            void Add(UserModel userModel);
        }
    }
    using AutoFacDemo.AutoFac.IRepository;
    using AutoFacDemo.AutoFac.IService;
    using AutoFacDemo.AutoFac.Modle;
    
    namespace AutoFacDemo.AutoFac.Service
    {
        public class UserService : IUserService
        {
            private IUserRepository _userRepository;
            /// <summary>
            /// 通过构造函数注入
            /// </summary>
            /// <param name="userRepository"></param>
            public UserService(IUserRepository userRepository)
            {
                this._userRepository = userRepository;
            }
            public void Add(UserModel userModel)
            {
                this._userRepository.AddUser(userModel);
            }
        }
    }

    至此,现在我们已经有了一组结构合理的依赖, 是时候接入Autofac了

    二、Autofac的使用

    1、把Autofac的引用添加进项目

     2、初始化AutoFac

      在应用启动的地方, 初始化AutoFac,需要添加一个 ContainerBuilder 并且通过它注册你的组件 ,组件 可以是一个表达式, .NET 类型, 或者其他暴露一个或多个 服务 的一段代码, 同时它也可以引入其他的依赖。我们在Global中初始化AutoFac,对于上边的MVC示例应用, 我们需要注册所有的组件 (类) 并且暴露他们的服务 (接口) , 这样对象就能很好地连接起来.

    using Autofac;
    using AutoFacDemo.AutoFac.IRepository;
    using AutoFacDemo.AutoFac.IService;
    using AutoFacDemo.AutoFac.Repository;
    using AutoFacDemo.AutoFac.Service;
    using System.Web.Mvc;
    using System.Web.Routing;
    
    namespace AutoFacDemo
    {
        public class MvcApplication : System.Web.HttpApplication
        {
            protected void Application_Start()
            {
                AreaRegistration.RegisterAllAreas();
                RouteConfig.RegisterRoutes(RouteTable.Routes);
                InitAutofac();
            }
            /// <summary>
            /// 初始化Autofac
            /// </summary>
            public void InitAutofac()
            {
                var builder = new ContainerBuilder();
                builder.RegisterType<UserRepository>().As<IUserRepository>();
                builder.RegisterType<UserService>().As<IUserService>();
                AutofacHelper.Container = builder.Build();
            }
        }
    }

    同时我们还要保存这个容器Container ,这样就可以在后续解析类型,所以定义一个公共类专门保存该容器:

    using Autofac;
    
    namespace AutoFacDemo
    {
        public class AutofacHelper
        {
            public static IContainer Container { get; set; }
    
            public static T GetService<T>()
            {
                return (T)Container?.Resolve(typeof(T));
            }
        }
    }

    现在我们已经拥有了一个注册了所有组件的容器 , 并且他们暴露了合适的服务,接下来就是使用它们

    3、应用执行

      注意:在应用程序执行阶段,你需要充分利用这些刚注册的组件。 你可以从一个生命周期中解析它们。容器本身是也是一个生命周期,从技术角度来说,你可以直接从Container解析组件,然而, 我们并不推荐直接这么做。解析组件时,根据定义的实例作用域, 创建一个对象的新实例 (解析一个组件大致相当于调用"new"实例化一个类)。 一些组件需要被释放 (实现IDisposable接口) ,Autofac会为你在生命周期释放时处理组件的释放。然而, 容器在应用的生命周期内一直存在,如果你直接从该容器中解析了太多东西,应用结束时将会有一堆东西等着被释放,这是非常不合适的 (很有可能造成"内存泄漏")。因此, 我们可以从容器中创建一个子生命周期 并从中解析。当你完成了解析组件, 释放掉子生命周期, 其他所有也就随之被一并清理干净了。(当使用Autofac 集成类库时, 大部分情况下子生命周期创建已经完成了, 因此无需考虑.)

      对于上边的MVC示例应用程序,我们在生命周期内实现"AddUser"方法并在结束调用后释放它。

    using AutoFacDemo.AutoFac.IService;
    using AutoFacDemo.AutoFac.Modle;
    using System.Web.Mvc;
    
    namespace AutoFacDemo.Controllers
    {
        public class HomeController : Controller
        {
            private readonly IUserService _userService;
            /// <summary>
            /// 构造函数注入
            /// </summary>
            /// <param name="userService"></param>
            public HomeController(IUserService userService)
            {
                _userService = userService;
            }
    
            // GET: Home
            public ActionResult Index()
            {
                UserModel userModel = new UserModel
                {
                    Id = "521",
                    UserName = "dachongzi"
                };
                _userService.Add(userModel);
                return View();
            }
        }
    }

    这样整个流程就走完了,但是运行起来HomeController中会报错“没有为该对象定义无参数的构造函数“,如果我们加上一个无参构造函数,程序就不走有参数的构造函数了,也就无法注入了,这是什么原因呢???主要是我们在Global中的InitAutofac()方法中没有注册MVC相关的组件,比如builder.RegisterControllers。这里就不详细介绍这块了,可以看文档。我们采用另一种方式注入:我们采用属性注入的方式:

    using AutoFacDemo.AutoFac.IService;
    using AutoFacDemo.AutoFac.Modle;
    using System.Web.Mvc;
    
    namespace AutoFacDemo.Controllers
    {
        public class HomeController : Controller
        {
            //IUserService _userService { get; }= AutofacHelper.GetService<IUserService>();      
            private readonly IUserService _userService = AutofacHelper.GetService<IUserService>();
            
            public ActionResult Index()
            {
                UserModel userModel = new UserModel
                {
                    Id = "521",
                    UserName = "dachongzi"
                };
                _userService.Add(userModel);
                return View();
            }
        }
    }

     完美解决。

    三、总结

      上边介绍了如何简单的使用AutoFac,但依然有很多你可以做的:

  • 相关阅读:
    WEB安全测试点总结
    接口自动化-testNG+poi(表格读写实例)
    接口自动化-testNG+httpclient(实例)
    接口自动化-javaTestNG框架-设计思路
    postman接口自动化(三)使用方法
    postman接口自动化(二)tests
    postman接口自动化(一)
    接口自动化-数据驱动-接口用例
    RF(三)robotframework工具介绍
    xpath轴定位详解
  • 原文地址:https://www.cnblogs.com/qtiger/p/13093739.html
Copyright © 2020-2023  润新知