Autofac之类型注册
本次主要学习一下Autofac中实现类型注册的几种方式,这里并不打算一开始就从基于接口开发的服务关联切入,而是先从一个简单的类型注册来学起,虽然实际开发中可能不会这么做,但是个人感觉从这里学起理解能能更加深刻
Autofac使用流程
- 按照Ioc(控制反转)的思想构建你的应用
- 添加Autofac引用
- 创建ContainerBuilder
- 注册组件
- 创建容器,将其保存以备后续使用
- 应用程序运行阶段
- 从容器中创建一个生命周期
- 在此生命周期作用域内解析组件实例
nuget添加Autofac引用

测试代码
这里提供一个很简单的类作为测试
class SqlDal
{
public void Add()
{
Console.WriteLine("向数据库写入一条数据");
}
}
创建容器
所有的Ioc框架都是类似的,它们的目的都是将类的实例化和调用解耦,调用者不再直接创建被调用者的实例,而是交由容器创建,只是在实现上有各自不同的方式
var builder = new ContainerBuilder();
普通注册
泛型注册:RegisterType<T>()
注册的类型必须在当前项目或被当前项目引用,因为使用泛型,必须类型明确
//将SqlDal类注册到容器中
builder.RegisterType<SqlDal>();
//通过Resolve()方法获取注册类型的实例,不推荐这种方式获取,这里的代码只作为测试
using (var container = builder.Build())
{
var sqlDal = container.Resolve<SqlDal>();
sqlDal.Add();
}
通过Type对象进行注册:RegisterType(Type)
被注册的类型可以不是被直接引用,但类型所在的程序集必须被加载,这种注册方式在有插件或类似需要动态加载程序集的情况下使用,通过扫描程序集,获取一些满足指定条件的类型,来进行注册。
通过在项目中引用CSharp.Tests.Model实现
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>泛型类型参数暂时不知道
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注册代码也会显得多而杂,当然,可以通过人工管理来控制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>();
Autofac之类型注册的更多相关文章
- Autofac全面解析系列(版本:3.5) – [使用篇(推荐篇):1.类型注册]
前言 Autofac Autofac是一套高效的依赖注入框架. Autofac官方网站:http://autofac.org/ Autofac在Github上的开源项目:https://github. ...
- 【反射】——Autofac 类型注册
Autofac是.net界一款轻量化的IOC组件,使用Autofac可以帮助完成代码中很多依赖注入工作.在以前文章中,介绍过Autofac的配置过程(http://www.cnblogs.com/Jn ...
- IoC容器Autofac正篇之类型注册(四)
Autofac类型注册 类型注册简单的从字面去理解就可以了,不必复杂化,只是注册的手段比较丰富. (一)类型/泛型注册 builder.RegisterType<Class1>(); 这种 ...
- IoC容器Autofac正篇之类型注册(五)
Autofac类型注册 类型注册简单的从字面去理解就可以了,不必复杂化,只是注册的手段比较丰富. (一)类型/泛型注册 builder.RegisterType<Class1>(); 这种 ...
- Autofac之类型关联
前面的学习一直使用的是直接注册类型并不是Autofac已经依赖注入的主要使用方式,最佳的依赖注入与Autofac的使用方式,都是要结合面向接口(抽象)编程的概念的.推崇的是依赖于抽象而不是具体 pub ...
- .NET手记-Autofac进阶(注册的概念 Registering Concepts)
通过创建ContainerBuilder并配置暴露的service(接口或者类型)来使用Autofac注册我们的组件. 组件(Components) 可以通过反射, 对象实例,或者lambda表达式来 ...
- autofac与unity注册类型的几个小区别
//以下两个注册,在Unity中是默认的 //注册控制器,否则不管接口注入还是属性注入都获取不到服务实例 Builder.RegisterControllers(typeof(MvcApplicati ...
- C++ 读取REG_SZ 、REG_DWORD 、REG_MULTI_SZ 类型注册表值
读取REG_SZ 类型的注册表键值 // 读取 REG_SZ 类型键值的代码 HKEY hKey = NULL; DWORD dwSize = ; DWORD dwDataType = ; LPBYT ...
- 关于XLL加载项动态加载、卸载的演示及XLL函数自定义类型注册的演示
1.在XLL中,把函数定义成不同的类型,在Excel中的实际效果也不同,具体如下: pxMacroType value ...
随机推荐
- web开发简史与技术选型
视频地址:http://v.youku.com/v_show/id_XMTQxNzM1MzAwOA==.html?firsttime=0&from=y1.4-2
- Lua中的一些库(1)
[数学库] 数学库(math)由一组标准的数学函数构成.这里主要介绍几个常用的函数,其它的大家可以自行百度解决. 三角函数(sin,cos,tan……)所有的三角函数都使用弧度单位,可以用函数deg( ...
- $Django 路飞之显示视频,Redis存购物车数据,优惠卷生成表,优惠卷的一个领取表。(知识小回顾)
知识小回顾之json序列化问题 精髓:支持python的几种数据类型(注意不是对象,不能放对象),其次是tuple变list. ensure_ascii:默认值True,如果dict内含有non-AS ...
- unity 网页加载AB问题
下载一次后会缓存,清理一下就能加载新的同名AB了 AssetBundle.onload
- C#中用ILMerge合并DLL和exe文件成一个exe文件或者DLL
ILMerge是一个将多个.NET程序集合并到一个程序集中的实用程序.它既可以作为 开源使用,也可以作为NuGet包使用. 如果您在使用它时遇到任何问题,请与我们联系.(mbarnett _at_ ...
- P4147 玉蟾宫--单调栈
P4147 玉蟾宫 题目背景 有一天,小猫rainbow和freda来到了湘西张家界的天门山玉蟾宫,玉蟾宫宫主蓝兔盛情地款待了它们,并赐予它们一片土地. 题目描述 这片土地被分成N*M个格子,每个格子 ...
- npm脚本传参问题
npm脚本传参问题(比如设置env参数) windows环境下: "build": "set NODE_ENV=dev&& gulp", &qu ...
- [慢更]Sublime Text 快捷键及使用过的插件
整理自己常用的sublime text命令和插件 1.pretty json Json 快速格式化,免去url访问json站点的烦恼. 摘自:https://segmentfault.com/a/11 ...
- codeforces 502 g The Tree
题解: 一道优秀的题目 有几种做法: 1.维护后缀和 刚开始我想的是维护前缀和 然后用$sum[x]-sum[y]>=dep[x]-dep[y]$来做 但是这样子树赋值为0这个操作就很难进行了 ...
- CodeForces - 833B The Bakery
题解: 线段树经典应用 首先暴力$f[i][j]$表示考虑前i位分成j段的最大值 转移$f[k][j-1]+cost(k+1,i)$枚举k转移 不同数的经典套路就是从它到它前驱这一段 于是维护每个数前 ...