AutoFac 基本使用-基于接口编程

AutoFac 基本使用-基于接口编程
1、 IOC 概念   GIthub地址:https://github.com/autofac/Autofac
之前我们写程序的时候所有对象都是程序员手动 new 的,当项目大了之后这样做的坏
处:
1) 各模块之间耦合严重;
2) 想要更换为其他实现类的时候很麻烦;
3) 有的程序员只关心“给我一个实现了***接口的类”,它不想关心这个类是怎么来的。
因此就诞生了 IOC(Inversion of Control,控制反转)容器。使用 IOC 容器后,不再是由
程序员自己 new 对象,而是由框架帮你 new 对象。
现在 IOC 有很多:Spring.Net、Unity、Castle、AutoFac 等。目前最火的就是 AutoFac。
使用 IOC 容器的时候,一般都是建议基于接口编程,也就是把方法定义到接口中,然后
再编写实现类。在使用的时候声明接口类型的变量、属性,由容器负责赋值。接口、实现
类一般都是定义在单独的项目中,这样减少互相的耦合。
刚接触这种思想的时候可能会感觉没用,但是随着使用深入就知道这样做的好处了。故
事:Eclipse 插件体系。
2、 AutoFac 基本使用
1) 创建接口项目和实现类项目;编写接口,编写实现类。
2) 安装 Install-Package Autofac
3) 编写一个接口 IService1,定义一个 Test()方法,定义实现类 Service1Impl
4) 基本用法:
方式一:
ContainerBuilder builder = new ContainerBuilder();
builder.RegisterType<Service1>().As<IService1>();
//注册实现类 Service1,当请求 IService1 接口的时候返回 Service1 的对象。原理代码,很少写
 
方式二:
IContainer resolver = builder.Build();
IService1 service1 = resolver.Resolve<IService1>();
方式三:
IContainer resolver = builder.Build();
builder.RegisterType<Service1>(). AsImplementedInterfaces();
这样请求 Service1 实现的任何接口的时候都会返回 Service1 对象。//原理代码,很少写
如果再有一个接口 IService2、Service2Impl 那再注册一次。
如果有很多接口、很多实现类,每次这样注册都很麻烦。因此可以如下:
 
方式四:
Assembly asm = Assembly.Load("实现类所在的程序集名称");
builder.RegisterAssemblyTypes(asm).AsImplementedInterfaces();//这是最常用的用法!
如果有多个程序集,RegisterAssemblyTypes 还接收多个程序集。注意:如果是多个程
序集,还要注意主项目要添加对相关程序集的引用。如果有个程序集,一定注意相关的类、接口一定要是 public
 

  

6) 如果 Resolve()抛异常或者返回 null,说明没有解析到实现类。如果有多个实现类,
resolver.Resolve<IService1>()只会返回其中一个类的对象。如果想返回多个实现类的对象,
改成 resolver.Resolve<IEnumerable<IService1>>()即可。
7) 如果一个实现类中定义了其他类型的接口属性,还可以在注册的时候加上
PropertiesAutowired,也就是.AsImplementedInterfaces().PropertiesAutowired()还会自动
给属性进行“注入”。如果可能有多个实现类,还可以声明 IEnumerable<IService1>类型
的属性。只有被 Autofac 创建出来的对象才会被“属性自动注入”
3、 AutoFac 对象的生命周期
根据到底创建多少个对象,AutoFac 有如下的生命周期,在 Register***后面以
Instance***()进行配置:
1) Per Dependency:每次请求 Resovle 都返回一个新对象:InstancePerDependency() 
2) Single Instance:单例,每次都返回同一个对象:SingleInstance()
3) PerLifetime Scope:每个生命周期一个对象;
4) InstancePerRequest:ASP.Net MVC 专用,每个请求一个对象。InstancePerRequest()
建议:最好配置成无状态的(实现类中不要有成员变量),使用单例方式。
4、AutoFac+ASP.NetMVC
AutoFac 还有 ASP.net MVC、WinForm 等的插件,用这些插件在这些平台下开发可以进
一步简化开发。
MVC 下的配置:
1) 安装 MVC 的 AutoFac 插件:Install-Package Autofac.Mvc5 较慢
2) 在 Global 中调用:
var builder = new ContainerBuilder();
builder.RegisterControllers(typeof(MvcApplication).Assembly).PropertiesAutowired();//把当前程序集中的 Controller 都注册
//不要忘了.PropertiesAutowired()
// 获取所有相关类库的程序集
Assembly[] assemblies = new Assembly[] { Assembly.Load("ZSZ.Service") };
builder.RegisterAssemblyTypes(assemblies)
.Where(type => !type.IsAbstract)
.AsImplementedInterfaces().PropertiesAutowired();
var container = builder.Build();

  

//注册系统级别的 DependencyResolver,这样当 MVC 框架创建 Controller 等对象的时候都
是管 Autofac 要对象。
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));//!!!
可选代码:
builder.RegisterFilterProvider();
//为 ActionFilter 注入
builder.RegisterAssemblyTypes(typeof(MvcApplication).Assembly)
.Where(type => typeof(ActionFilterAttribute).IsAssignableFrom(type) && !type.IsAbstract)
.PropertiesAutowired();

 

3) 如果想为自定义 ModelBinder 等注入,还可以使用
builder.RegisterModelBinders()等方法
4) 这样在 Controller 中只要声明 Service 的属性即可,AutoFac 会自动完成属性注入。 如鹏网《掌上租》项目课件 rupeng.com
在 ActionFilter 也可以这样用。
4) 只有 Autofac 帮我们创建的对象才有可能给我们自动进行属性的赋值 PropertiesAutowired。但是
在没有注入的地方(比如 Helper 中),如果想获取对象,就还要
ICityService cityService = DependencyResolver.Current.GetService<ICityService>()
5)如果在Quartz等 单 独 的 线 程 中 , 无 法 通 过
DependencyResolver.Current.GetService<ICityService>()获取,就要
var container = AutofacDependencyResolver.Current.ApplicationContainer;
using (container.BeginLifetimeScope())
{
    cityService = container.Resolve<ICityService>();
}
 

  

posted @ 2021-10-26 22:45  Tammytan  阅读(357)  评论(0编辑  收藏  举报