第二节:框架前期准备篇之AutoFac常见用法总结
2018-08-21 07:39
423 查看
一. 说在前面的话
凡是大约工作在两年以上的朋友们,或多或少都会接触到一些框架搭建方面的知识,只要一谈到框架搭建这个问题或者最佳用法这个问题,势必会引起一点点小小的风波,我说我的好,他说他的好,非常容易骂架,所以在本节乃至该系列我仅仅是总结了一下自己日常中的一些用法,谈一下自己浅陋的见解,谈不上最佳,只要不误导新手 能有点帮助作用就可以了,如您不喜欢,请“右上角 谢谢”。
在框架搭建过程中,在层与层的解耦方面,势必会涉及到IOC框架,.Net 平台下我用过的IOC框架主要是: Spring.Net 、Unity、AutoFac,当然还有Castle(我没用过,就不发表任何评论了), 在用过的IOC框架中,Spring.Net 相对很老了,貌似在2015年就不在更新了,但基本的功能也够用了。 现阶段用的最多的就是Unity和AutoFac了,版本更新也比较快,Unity大约一年前写过两篇文章了,本次在该框架系列也会考虑更新一下Unity,本节主要介绍一下AutoFac的几个基本用法。
先说一下两个概念IOC和DI,我的理解:
① IOC:调用者不再创建(不自己new)被调用者的实例,而是交给容器去创建(AutoFac就充当这里的容器),这就是控制反转。
② DI:容器创建好的实例再注入调用者的过程,就是依赖注入(比如:属性注入、构造函数注入等)。
AutoFac的信息:
① 官网地址:https://autofac.org/
② 官方文档:http://autofac.readthedocs.io/en/latest/index.html
③ 最新版本:4.8.1 (截止2018-08-21)
本节的内容主要包括:
1. 在使用IOC框架之前的几种创建对象的方式。
2. AutoFac的基本用法和几种生命周期。
3. AutoFac和Asp.Net MVC5进行整合,利用属性的方式进行注入。
事先说明一下本节要用到的实现类和接口类:
(1). Ypf.BLL层中包括:CatBLL、DogBLL、RoleBLL、UserBLL。
RoleBLL
下面测试一下不是AutoFac创建的对象能否实现属性的自动注入,新建TempTest类,在里面声明IUserBLL属性,并且在方法中进行调用,然后new一个TempTest对象,对该showMsg方法进行调用,发现报空指针错误,说明userBLL属性为空,没能自动注入。
5. 1个接口多个实现类的情况
背景:1个接口有多个实现类的情况(DogBLL 和 CatBLL 都实现了 IAnimalBLL接口)
分析:resolver.Resolve<IAnimalBLL>();只会返回其中一个类的对象
解决方案:如果想返回多个实现类的对象,改成 resolver.Resolve<IEnumerable<IAnimalBLL>>()即可。
6. AutoFac的几种常见生命周期
1. InstancePerDependency:每次请求 Resovle都返回一个新对象。InstancePerDependency()【这也是默认的创建实例的方式。】
2. SingleInstance: 单例,只有在第一次请求的时候创建 。SingleInstance()
3. InstancePerRequest:ASP.Net MVC 专用,每次http请求内一个对象(也可以理解为一个方法内)。InstancePerRequest() 和 CallContext神似
4. InstancePerLifetimeScope:在一个生命周期域中,每一个依赖或调用创建一个单一的共享的实例,且每一个不同的生命周期域,实例是唯一的,不共享的。
下面测试一下前两种生命周期
情况1
结果:False,证明InstancePerDependency 每次都创建一个新对象
情况2
结果:true,证明SingleInstance 每次都返回同一个对象。
四. AutoFac与MVC整合
1. Controller中通过属性注入对象
步骤1:在Ypf.MVC层中添加对Ypf.IBLL层的引用,并将Ypf.BLL的程序集拷贝到 Ypf.MVC中,或者直接改一下Ypf.BLL输出路径。
步骤2:通过Nuget安装程序集 Autofac.Mvc5。
步骤3:在Gloabl 注册 AutoFac代码。
步骤4:在Controller中进行调用。
2. 普通类中通过代码获取对象
在一个没有通过AutoFac注册的普通类中如何获取接口对象呢,通过DependencyResolver.Current.GetService<IUserBLL>();来获取。
代码如下:
3. 如何在普通类中通过属性的方式注入对象
需要有两个条件:
①: 这个普通类的创建必须在Global中通过AutoFac来进行注册。
②: 获取这个类的时候必须通过 DependencyResolver.Current.GetService<IUserBLL>(); 这种方式来获取。
在Global文件中注册该普通类
该普通类CommonHelp的获取必须通过DependencyResolver.Current.GetService<CommonHelp>();方式来获取。
4. 在单独线程中获取对象
比如在Quartz.Net 中,需要通过下面代码来获取。
详细代码如下:
!
作 者 : Yaopengfei(姚鹏飞)
博客地址 : http://www.cnblogs.com/yaopengfei/
声 明1 : 本人才疏学浅,用郭德纲的话说“我是一个小学生”,如有错误,欢迎讨论,请勿谩骂^_^。
声 明2 : 原创博客请在转载时保留原文链接或在文章开头加上本人博客地址,否则保留追究法律责任的权利。
凡是大约工作在两年以上的朋友们,或多或少都会接触到一些框架搭建方面的知识,只要一谈到框架搭建这个问题或者最佳用法这个问题,势必会引起一点点小小的风波,我说我的好,他说他的好,非常容易骂架,所以在本节乃至该系列我仅仅是总结了一下自己日常中的一些用法,谈一下自己浅陋的见解,谈不上最佳,只要不误导新手 能有点帮助作用就可以了,如您不喜欢,请“右上角 谢谢”。
在框架搭建过程中,在层与层的解耦方面,势必会涉及到IOC框架,.Net 平台下我用过的IOC框架主要是: Spring.Net 、Unity、AutoFac,当然还有Castle(我没用过,就不发表任何评论了), 在用过的IOC框架中,Spring.Net 相对很老了,貌似在2015年就不在更新了,但基本的功能也够用了。 现阶段用的最多的就是Unity和AutoFac了,版本更新也比较快,Unity大约一年前写过两篇文章了,本次在该框架系列也会考虑更新一下Unity,本节主要介绍一下AutoFac的几个基本用法。
先说一下两个概念IOC和DI,我的理解:
① IOC:调用者不再创建(不自己new)被调用者的实例,而是交给容器去创建(AutoFac就充当这里的容器),这就是控制反转。
② DI:容器创建好的实例再注入调用者的过程,就是依赖注入(比如:属性注入、构造函数注入等)。
AutoFac的信息:
① 官网地址:https://autofac.org/
② 官方文档:http://autofac.readthedocs.io/en/latest/index.html
③ 最新版本:4.8.1 (截止2018-08-21)
本节的内容主要包括:
1. 在使用IOC框架之前的几种创建对象的方式。
2. AutoFac的基本用法和几种生命周期。
3. AutoFac和Asp.Net MVC5进行整合,利用属性的方式进行注入。
事先说明一下本节要用到的实现类和接口类:
(1). Ypf.BLL层中包括:CatBLL、DogBLL、RoleBLL、UserBLL。
public class RoleBLL : IRoleBLL { public IUserBLL userBLL { get; set; } /// <summary> /// 展示角色信息 /// </summary> /// <returns></returns> public string ShowRoleInfor() { return "我是管理员角色"; } public string ShowDIDemo() { return "哈哈:" + userBLL.GetUserInfor(); } }
RoleBLL
{ ContainerBuilder builder = new ContainerBuilder(); //加载实现类的程序集 Assembly asm = Assembly.Load("Ypf.BLL"); builder.RegisterAssemblyTypes(asm).AsImplementedInterfaces().PropertiesAutowired(); IContainer resolver = builder.Build(); IRoleBLL iRoleBLL = resolver.Resolve<IRoleBLL>(); var r1 = iRoleBLL.ShowDIDemo(); Console.WriteLine(r1); }
下面测试一下不是AutoFac创建的对象能否实现属性的自动注入,新建TempTest类,在里面声明IUserBLL属性,并且在方法中进行调用,然后new一个TempTest对象,对该showMsg方法进行调用,发现报空指针错误,说明userBLL属性为空,没能自动注入。
public class TempTest { public IUserBLL userBLL { get; set; } public void showMsg() { Console.WriteLine(userBLL.GetUserInfor()); } }
//测试自己new的对象不能实现属性的自动注入 //下面代码报空指针错误 { TempTest t = new TempTest(); t.showMsg(); }
5. 1个接口多个实现类的情况
背景:1个接口有多个实现类的情况(DogBLL 和 CatBLL 都实现了 IAnimalBLL接口)
分析:resolver.Resolve<IAnimalBLL>();只会返回其中一个类的对象
解决方案:如果想返回多个实现类的对象,改成 resolver.Resolve<IEnumerable<IAnimalBLL>>()即可。
{ ContainerBuilder builder = new ContainerBuilder(); //加载实现类的程序集 Assembly asm = Assembly.Load("Ypf.BLL"); builder.RegisterAssemblyTypes(asm).AsImplementedInterfaces().PropertiesAutowired(); IContainer resolver = builder.Build(); //返回 CalBLL 和 DogBLL 中的一个 //{ // IAnimalBLL iAnimalBLL = resolver.Resolve<IAnimalBLL>(); // var r1 = iAnimalBLL.Introduce(); // Console.WriteLine(r1); //} //如何获取多个呢? { IEnumerable<IAnimalBLL> blls = resolver.Resolve<IEnumerable<IAnimalBLL>>(); foreach (IAnimalBLL animalBLL in blls) { Console.WriteLine(animalBLL.GetType()); Console.WriteLine(animalBLL.Introduce()); } } }
6. AutoFac的几种常见生命周期
1. InstancePerDependency:每次请求 Resovle都返回一个新对象。InstancePerDependency()【这也是默认的创建实例的方式。】
2. SingleInstance: 单例,只有在第一次请求的时候创建 。SingleInstance()
3. InstancePerRequest:ASP.Net MVC 专用,每次http请求内一个对象(也可以理解为一个方法内)。InstancePerRequest() 和 CallContext神似
4. InstancePerLifetimeScope:在一个生命周期域中,每一个依赖或调用创建一个单一的共享的实例,且每一个不同的生命周期域,实例是唯一的,不共享的。
下面测试一下前两种生命周期
情况1
{ ContainerBuilder builder = new ContainerBuilder(); //加载实现类的程序集 Assembly asm = Assembly.Load("Ypf.BLL"); builder.RegisterAssemblyTypes(asm).AsImplementedInterfaces().PropertiesAutowired().InstancePerDependency(); IContainer resolver = builder.Build(); IUserBLL u1 = resolver.Resolve<IUserBLL>(); IUserBLL u2 = resolver.Resolve<IUserBLL>(); Console.WriteLine(object.ReferenceEquals(u1, u2)); }
结果:False,证明InstancePerDependency 每次都创建一个新对象
情况2
{ ContainerBuilder builder = new ContainerBuilder(); //加载实现类的程序集 Assembly asm = Assembly.Load("Ypf.BLL"); builder.RegisterAssemblyTypes(asm).AsImplementedInterfaces().PropertiesAutowired().SingleInstance(); IContainer resolver = builder.Build(); IUserBLL u1 = resolver.Resolve<IUserBLL>(); IUserBLL u2 = resolver.Resolve<IUserBLL>(); Console.WriteLine(object.ReferenceEquals(u1, u2)); }
结果:true,证明SingleInstance 每次都返回同一个对象。
四. AutoFac与MVC整合
1. Controller中通过属性注入对象
步骤1:在Ypf.MVC层中添加对Ypf.IBLL层的引用,并将Ypf.BLL的程序集拷贝到 Ypf.MVC中,或者直接改一下Ypf.BLL输出路径。
步骤2:通过Nuget安装程序集 Autofac.Mvc5。
步骤3:在Gloabl 注册 AutoFac代码。
public class MvcApplication : System.Web.HttpApplication { protected void Application_Start() { AreaRegistration.RegisterAllAreas(); FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); RouteConfig.RegisterRoutes(RouteTable.Routes); BundleConfig.RegisterBundles(BundleTable.Bundles); /***********下面是AutoFac的注册*************/ //1. 创建容器 var builder = new ContainerBuilder(); //2. 把当前程序集中的所有Controller都注册进来 builder.RegisterControllers(typeof(MvcApplication).Assembly).PropertiesAutowired(); //3. 把Ypf.BLL中的所有类注册给它的全部实现接口,并且把实现类中的属性也进行注册 //{ Assembly asmService = Assembly.Load("Ypf.BLL"); } //PS:这里可以配合配置文件的,将Ypf.BLL写到配置文件中 string DllName = ConfigurationManager.AppSettings["DllName"]; Assembly asmService = Assembly.Load(DllName); builder.RegisterAssemblyTypes(asmService).Where(t => !t.IsAbstract).AsImplementedInterfaces().PropertiesAutowired(); var container = builder.Build(); //4. 下面这句话表示当mvc创建controller对象的时候,都是由AutoFac为我们创建Controller对象 DependencyResolver.SetResolver(new AutofacDependencyResolver(container)); } }
步骤4:在Controller中进行调用。
2. 普通类中通过代码获取对象
在一个没有通过AutoFac注册的普通类中如何获取接口对象呢,通过DependencyResolver.Current.GetService<IUserBLL>();来获取。
代码如下:
public class Utils { public static string Test() { IUserBLL userBLL = DependencyResolver.Current.GetService<IUserBLL>(); return userBLL.GetUserInfor(); } }
3. 如何在普通类中通过属性的方式注入对象
需要有两个条件:
①: 这个普通类的创建必须在Global中通过AutoFac来进行注册。
②: 获取这个类的时候必须通过 DependencyResolver.Current.GetService<IUserBLL>(); 这种方式来获取。
在Global文件中注册该普通类
该普通类CommonHelp的获取必须通过DependencyResolver.Current.GetService<CommonHelp>();方式来获取。
4. 在单独线程中获取对象
比如在Quartz.Net 中,需要通过下面代码来获取。
详细代码如下:
{ //1.创建作业调度池(Scheduler) IScheduler scheduler = StdSchedulerFactory.GetDefaultScheduler(); //2.创建一个具体的作业即job (具体的job需要单独在一个文件中执行) var job = JobBuilder.Create<HelloJob>().Build(); //3.创建并配置一个触发器即trigger 1s执行一次 var trigger = TriggerBuilder.Create().WithSimpleSchedule(x => x.WithIntervalInSeconds(1) .RepeatForever()).Build(); //4.将job和trigger加入到作业调度池中 scheduler.ScheduleJob(job, trigger); //5.开启调度 scheduler.Start(); }
public class HelloJob:IJob { void IJob.Execute(IJobExecutionContext context) { IUserBLL userBLL; var container = AutofacDependencyResolver.Current.ApplicationContainer; using (container.BeginLifetimeScope()) { userBLL = container.Resolve<IUserBLL>(); } //下面代码只是测试 Console.WriteLine(userBLL.GetUserInfor()); } }
!
作 者 : Yaopengfei(姚鹏飞)
博客地址 : http://www.cnblogs.com/yaopengfei/
声 明1 : 本人才疏学浅,用郭德纲的话说“我是一个小学生”,如有错误,欢迎讨论,请勿谩骂^_^。
声 明2 : 原创博客请在转载时保留原文链接或在文章开头加上本人博客地址,否则保留追究法律责任的权利。
相关文章推荐
- CodeIgniter框架常见用法工作总结
- Android Intent 常见用法总结
- smarty学习笔记之常见代码段用法总结
- EasyUI——常见用法总结
- 购物网第一阶段总结笔记1:友情链接模块前期准备
- Java8中Optional的一些常见错误用法总结
- NSPredicate用法总结(Cocoa框架中的NSPredicate用于查询,原理和用法都类似于SQL中的where,作用相当于数据库的过滤取)
- 第三节:框架前期准备篇之利用Newtonsoft.Json改造MVC默认的JsonResult
- [阶段总结]一个多月的求职从心理准备、实际准备到网申、笔试、面试的整个前期阶段的总结
- java中String的常见用法总结
- Android onInterceptTouchEvent()和onTouchEvent()例子和总结——Launcher前期准备
- 总结UIView常见的用法
- Easy-ui常见用法总结
- gotoNetPage 常见用法总结
- Java基础知识强化之集合框架笔记74:各种集合常见功能 和 遍历方式总结
- 面试准备之常见排序算法的总结!
- C++序列容器之 vector常见用法总结
- 第三节:框架前期准备篇之利用Newtonsoft.Json改造MVC默认的JsonResult
- NSDictionary的常见用法总结
- Android onInterceptTouchEvent()和onTouchEvent()例子和总结——Launcher前期准备