本次主要学习一下Autofac中实现类型注册的几种方式,这里并不打算一开始就从基于接口开发的服务关联切入,而是先从一个简单的类型注册来学起,虽然实际开发中可能不会这么作,可是我的感受从这里学起理解能能更加深入mysql
这里提供一个很简单的类做为测试sql
class SqlDal { public void Add() { Console.WriteLine("向数据库写入一条数据"); } }
建立容器数据库
全部的Ioc框架都是相似的,它们的目的都是将类的实例化和调用解耦,调用者再也不直接建立被调用者的实例,而是交由容器建立,只是在实现上有各自不一样的方式框架
var builder = new ContainerBuilder();
泛型注册:RegisterType<T>()ide
注册的类型必须在当前项目或被当前项目引用,由于使用泛型,必须类型明确函数
//将SqlDal类注册到容器中 builder.RegisterType<SqlDal>();
//经过Resolve()方法获取注册类型的实例,不推荐这种方式获取,这里的代码只做为测试 using (var container = builder.Build()) { var sqlDal = container.Resolve<SqlDal>(); sqlDal.Add(); }
经过Type对象进行注册:RegisterType(Type) 学习
被注册的类型能够不是被直接引用,但类型所在的程序集必须被加载,这种注册方式在有插件或相似须要动态加载程序集的状况下使用,经过扫描程序集,获取一些知足指定条件的类型,来进行注册。测试
经过在项目中引用CSharp.Tests.Model实现ui
Assembly assembly = Assembly.Load("CSharp.Tests.Model"); var type = assembly.GetType("CSharp.Tests.Model.AutofacTestModel"); builder.RegisterType(type); using (var container = builder.Build()) { var model = container.Resolve<AutofacTestModel>(); Console.WriteLine(model.SayHello()); }
TODO:将dll拷贝到bin目录下不用引用dll也能够实现注册,可是如何将类型做为Resolve<T>泛型类型参数暂时不知道spa
lambda表达式注册
以前的方式都是经过类型进行直接注册的,这种注册方式,在获取时,会直接经过构造函数new出对象,不会作更多的操做。有时咱们但愿可以在获取对象时可以自动的作更多的事情时,咱们能够经过lambda注册来解决,在lambda表达式中能够作不少事,包括一些属性注入、方法注入、条件判断等等
class SqlDal { public string Str { get; set; } public void Add() { Console.WriteLine("向SqlServer数据库写入一条数据,Str={0}", Str); } }
builder.Register(type => { //经过lambda表达式注册时添加属性值 var sqlDal = new SqlDal(); sqlDal.Str = "Test"; return sqlDal; });
实例注册
经过RegisterInstance进行实例注册,进行实例注册时,须要注意,实例注册能够做为一种单例注册的方式,也就是在后面经过Autofac获取SqlDal对象时,获取到的是注册时的那个对象。而且,若是一个在某处修改了该对象,其余地方再获取时,获取到的就是修改后的对象
builder.RegisterInstance(new SqlDal()); using (var container = builder.Build()) { var sqlDal = container.Resolve<SqlDal>(); sqlDal.Add(); }
泛型注册
经过RegisterGeneric() 这个方法实现泛型注册,在容器中能够建立出泛型的具体对象
builder.RegisterGeneric(typeof(List<>)).As(typeof(IList<>)).InstancePerLifetimeScope(); using (IContainer container = builder.Build()) { var ListString = container.Resolve<IList<string>>(); }
Module注册
在平常开发中,可能不一样开发会负责不一样的模块进行单独开发。在开发过程当中,不一样模块不一样开发可能都有本身的类型须要注册到autofac中,可是若是每一个人在注册时,都去修改一个指定地方的代码,这在进行代码合并时,是使人痛苦的。更好的方式是,每一个开发不一样的模块都有本身指定的类型注册区域,这样,在代码合并时,会减小不少代码冲突
class SqlModule : Autofac.Module { protected override void Load(ContainerBuilder builder) { builder.RegisterType<SqlDal>(); } } class MySqlModule : Autofac.Module { protected override void Load(ContainerBuilder builder) { builder.RegisterType<MySqlDal>(); } }
builder.RegisterModule<SqlModule>(); builder.RegisterModule<MySqlModule>(); using (var container = builder.Build()) { var sqldal = container.Resolve<SqlDal>(); sqldal.Add(); var mysqldal = container.Resolve<MySqlDal>(); mysqldal.Add(); }
上述代码中,有两个继承自Module类的类:SqlModule、MySqlModule,这两个类型重写了父类的Load方法,并在load方法中,分别注册了SqlDal与MySqlDal类型。而后在主程序中,经过RegisterModule对Module进行注册。
经过这种方式,不一样的开发就能够各自建立一个类继承自Module,而后重写Load方法,在Load方法进行本身的类型注册,最后再进行Module的统一注册(这里还能够经过自定义实现了IModule接口的类型,而后在RegisterModule时传入来达到一样的效果而且功能也更多)
默认的注册
若是一个类型被屡次注册,以最后注册的为准。经过使用PreserveExistingDefaults() 修饰符,能够指定某个注册为非默认值。
上面的例子中都是将单个类型注册到容器中,而在实际开发中可能存在多个类型须要注册,难道要每一个类型挨个注册吗?Autofac中为这种状况提供了程序集注册的方式
程序集批量注册
类型注册中提到了经过扫描程序集,来获取部分类型进行注册。Autofac对此提供了一个方便的方式,能够直接经过程序集来筛选类型注册
//获取当前应用程序加载程序集(C/S应用中使用)
var assembly = Assembly.GetExecutingAssembly();
//注册全部程序集类定义的非静态类型
builder.RegisterAssemblyTypes(assembly);
程序集过滤后批量注册
上面的方式达到了批量的效果,可是一般并不须要把全部的类型都进行注册,因此Autofac提供了几种过滤方式
builder.RegisterAssemblyTypes(assembly).Where(type => type.Namespace.Equals("CSharp.Tests.框架学习"));
排除指定类型的注册
使用Except排除指定类型的注册
builder.RegisterAssemblyTypes(assembly).Where(type => type.Namespace.Contains("CSharp.Tests")).Except<CSharp.Tests.设计思想.SqlDal>();
Module注册,为多人开发提供了一种方便的注册方式,可是也能够发现,这种方式,仍是会须要手动注册Module,若是Module过多,Module注册代码也会显得多而杂,固然,能够经过人工管理来控制Module的量。可是Autofac还提供了一种更方便的方式,而且,对于相似Orchard的模块开发(子模块与主模块无引用关系,经过程序集加载方式来加载子模块)或是插件开发,咱们没办法经过Registerodule来注册无直接引用关系的Module
var assembly = Assembly.GetExecutingAssembly();
//注册assembly程序集中全部实现了IModule接口的类型(多层继承也算),这样只须要取出全部程序集,而后经过RegisterAssemblyModules进行一次性注册,就能够自动注册全部Module了
builder.RegisterAssemblyModules(assembly); builder.RegisterAssemblyModules<SqlModule>(assembly);//指定泛型类型只注册assembly程序集中继承自SqlModule的Module
被注册的类型须要在指定类的命名空间中
var assembly = Assembly.GetExecutingAssembly();builder.RegisterAssemblyTypes(assembly).InNamespaceOf<AutofacTest>();