IOC-AutoFac
学习过程中参考博客:
AutoFac文档:http://www.cnblogs.com/wolegequ/archive/2012/06/09/2543487.html
AutoFac使用方法总结:Part I:http://niuyi.github.io/blog/2012/04/06/autofac-by-unit-test/
为什么使用AutoFac?
Autofac是.NET领域最为流行的IOC框架之一,传说是速度最快的一个:
优点:
- 它是C#语言联系很紧密,也就是说C#里的很多编程方式都可以为Autofac使用,例如可以用Lambda表达式注册组件
- 较低的学习曲线,学习它非常的简单,只要你理解了IoC和DI的概念以及在何时需要使用它们
- XML配置支持
- 自动装配
- 与Asp.Net MVC 集成
- 微软的Orchad开源程序使用的就是Autofac,从该源码可以看出它的方便和强大
上面的优点我也是拷的别人文章里面的,上面的这个几乎所有讲Autofac博文都会出现的。这个也是首次学习,所以我们还是记录的细一点。
怎么使用Autofac
通过VS中的NuGet来加载AutoFac,引入成功后引用就会出现Autofac。
1、我们做一个简单的例子先用一下
就拿数据访问来做案例把,一个数据请求有两个类,一个是Oracle 一个是SQLSERVER。我们在使用的时候可以选择调用那个数据库。
1.1 我们先定义一个数据访问的接口和访问类。
/// <summary>
/// 数据源操作接口
/// </summary>
public interface IDataSource
{
/// <summary>
/// 获取数据
/// </summary>
/// <returns></returns>
string GetData();
}/// <summary>
/// SQLSERVER数据库
/// </summary>
class Sqlserver : IDataSource
{
public string GetData()
{
return "通过SQLSERVER获取数据";
}
}/// <summary>
/// ORACLE数据库
/// </summary>
public class Oracle : IDataSource
{
public string GetData()
{
return "通过Oracle获取数据";
}
}最普通的方式大家都会的吧! 如果最普通的方式调用SQLSERVER怎么写?
static void Main(string[] args)
{
IDataSource ds = new Sqlserver(); Console.WriteLine(ds.GetData()); Console.ReadLine();
}调用Oracle的话new Oracle()就可以了。如果这个都不能理解的话,那学习这个你就很费劲了。改进一下代码。我们在加入一个DataSourceManager类来看一下
/// <summary>/// 数据源管理类/// </summarypublic class DataSourceManager
{ IDataSource _ds;
/// <summary>
/// 根据传入的类型动态创建对象
/// </summary>
/// <param name="ds"></param>
public DataSourceManager(IDataSource ds)
{
_ds = ds;
} public string GetData()
{
return _ds.GetData();
}
}这样写的好处是什么,这样加入加入新的数据源,只用调用的时候传入这个对象就可以,就会自动创建一个对应的对象。那接下如果要调用SQLSERVER怎么写。看代码
DataSourceManager dsm = new DataSourceManager(new Sqlserver());Console.WriteLine(dsm.GetData()); Console.ReadLine();1.2 注入实现构造函数注入
上面的DataSourceManager的动态创建的方式就是因为又有个带IDataSource的参数的构造函数,只要调用者传入实现该接口的对象,就实现了对象创建。
那我们看看怎么使用AutoFac注入实现构造函数注入
var builder = new ContainerBuilder();
builder.RegisterType<DataSourceManager>();
builder.RegisterType<Sqlserver>().As<IDataSource>(); using (var container = builder.Build())
{
var manager = container.Resolve<DataSourceManager>();
Console.WriteLine(manager.GetData()); Console.ReadLine();
}上面的就是AutoFac构造函数注入,他给IDataSource注入的是Sqlserver所以我们调用的数据,返回的就是Sqlserver数据。那下面我们具体的了解一下AutoFac的一些方法
1.3 Autofac方法说明
(1)builder.RegisterType<Object>().As<Iobject>():注册类型及其实例。例如上面就是注册接口IDataSource的实例Sqlserver(2)IContainer.Resolve<IDAL>():解析某个接口的实例。例如一下代码,我可以解析接口返回的就是Sqlserver实例var builder = new ContainerBuilder();
//builder.RegisterType<DataSourceManager>();
builder.RegisterType<Sqlserver>().As<IDataSource>();using (var container = builder.Build())
{
var manager = container.Resolve<IDataSource>();
Console.WriteLine(manager.GetData());Console.ReadLine();
}(3)builder.RegisterType<Object>().Named<Iobject>(string name):为一个接口注册不同的实例。有时候难免会碰到多个类映射同一个接口,比如Sqlerver和Oracle都实现了IDalSource接口,为了准确获取想要的类型,就必须在注册时起名字。
12345678var
builder =
new
ContainerBuilder();
builder.RegisterType<Sqlserver>().Named<IDataSource>(
"SqlServer"
); builder.RegisterType<Oracle>().Named<IDataSource>(
"Oracel"
);
using
(
var
container = builder.Build())
{
var
manager = container.ResolveNamed<IDataSource>(
"Oracel"
);
Console.WriteLine(manager.GetData());
Console.ReadLine();
}
运行后的代码。
(4)IContainer.ResolveNamed<IDAL>(string name):解析某个接口的“命名实例”。例如上面的实例最后一行代码container.ResolveNamed<IDataSource>("Oracel"); 就是解析IDataSource的命名实例Oracel。
(5)builder.RegisterType<Object>().Keyed<Iobject>(Enum enum):以枚举的方式为一个接口注册不同的实例。有时候我们会将某一个接口的不同实现用枚举来区分,而不是字符串。
这个方法是完全可以替代builder.RegisterType<Object>().Named<Iobject>(string name),这个列子就不演示了吧!和上面的一个意思。(6)IContainer.ResolveKeyed<IDAL>(Enum enum):根据枚举值解析某个接口的特定实例。这个和上面的都一样 也就不演示了。(7)builder.RegisterType<Worker>().InstancePerDependency():用于控制对象的生命周期,每次加载实例时都是新建一个实例,默认就是这种方式。调用的话builder.RegisterType<Sqlserver>().Keyed<IDataSource>("Sqlserver").InstancePerDependency();(8)builder.RegisterType<Worker>().SingleInstance():用于控制对象的生命周期,每次加载实例时都是返回同一个实例(9)IContainer.Resolve<T>(NamedParameter namedParameter):在解析实例T时给其赋值,这个就是给你定义的方法的参数传值。
12345678910111213141516IDataSource _ds;
string
Name;
/// <summary>
/// 根据传入的类型动态创建对象
/// </summary>
/// <param name="ds"></param>
public
DataSourceManager(
string
name, IDataSource ds)
{
_ds = ds;
Name = name;
}
public
string
GetData()
{
returnName +
":"
+ _ds.GetData();
}
我把DataSourceManager的构造方法加了个name参数,然后我调用的时候:
var manager = container.Resolve<DataSourceManager>(new NamedParameter("name", "STONE刘先生"));运行后的代码:
1.4 通过配置的方式使用AutoFac
在演示一下怎么通过配置文件来配置注册。这块就简单讲,下面的是我的web.config。
<configuration>
<configSections>
<section name="autofac" type="Autofac.Configuration.SectionHandler,Autofac.Configuration"></section>
</configSections>
<autofac defaultAssembly="AutoFacDemo">
<components>
<component type="AutoFacDemo.Model.Oracle,AutoFacDemo" service="AutoFacDemo.Model.IDataSource" />
</components>
</autofac>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
</configuration>后台的调用代码
var builder = new ContainerBuilder();
builder.RegisterType<DataSourceManager>();
builder.RegisterModule(new ConfigurationSettingsReader("autofac"
)); using (var container = builder.Build())
{
var manager = container.Resolve<DataSourceManager>(new NamedParameter("name", "STONE刘先生"));
Console.WriteLine(manager.GetData()); Console.ReadLine();
}这里需要注意的是需要引用Autofac.Configuration.dll,否则没有办法使用ConfigurationSettingsReader。
还有一个需要注意的就是你的配置文件要命名空间,类名要写对。
动手尝试一下吧!
MVC下面使用Autofac
引用和上面的控制台程序的原理是一模一样的。但是区别就在于要多添加一个引用
案例还是用上面的案例。我是把之前的接口和类拷贝到MVC项目里面作为下面演示。代码就不在写出来了,一模一样的。
1、首先在函数Application_Start() 注册自己的控制器类
MVC下怎么配置可以直接看如下代码,我把注释写的也很详细。
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RouteConfig.RegisterRoutes(RouteTable.Routes); //创建autofac管理注册类的容器实例
var builder = new ContainerBuilder();
//下面就需要为这个容器注册它可以管理的类型
//builder的Register方法可以通过多种方式注册类型,之前在控制台程序里面也演示了好几种方式了。
builder.RegisterType<Sqlserver>().As<IDataSource>(); //builder.RegisterType<DefaultController>().InstancePerDependency();
//使用Autofac提供的RegisterControllers扩展方法来对程序集中所有的Controller一次性的完成注册
builder.RegisterControllers(Assembly.GetExecutingAssembly());
//生成具体的实例
var container = builder.Build();
//下面就是使用MVC的扩展 更改了MVC中的注入方式.
DependencyResolver.SetResolver(new AutofacDependencyResolver(container)); }需要解释的是:
1、大家看下面的这句,这句的作用就是再MVC下面你必须要注册一下Controller,否则没有办法注入。
//使用Autofac提供的RegisterControllers扩展方法来对程序集中所有的Controller一次性的完成注册
builder.RegisterControllers(Assembly.GetExecutingAssembly());我们通过使用RegisterControllers就可以解决。那如果不用RegisterControllers 我就想一个个注册的话怎么弄?学技术有时候不要只管会用有的时候你也要理解人家提供的方法背后是怎么做的。看到这里你知道怎么做么?先考虑1分钟,不要记得往下看。答案其实在上面讲控制台程序使用Autofac的时候已经讲过了。好吧,我来详细讲一下,我先把之前控制台程序的代码贴出来。
public class DataSourceManager
{
IDataSource _ds;
string Name;
/// <summary>
/// 根据传入的类型动态创建对象
/// </summary>
/// <param name="ds"></param>public DataSourceManager(string
name, IDataSource ds)
{
_ds = ds;
Name = name;
}
public string GetData()
{
return Name + ":" + _ds.GetData();
}
}这个类还记得吗?不记得在看之前写的文章。这个类有个IDataSource 作为参数的构造方法。然后我们在看一下使用时候的代码?var builder = new ContainerBuilder();
builder.RegisterType<DataSourceManager>();
builder.RegisterType<Sqlserver>().As<IDataSource>();
using (var container = builder.Build())
{ var manager = container.Resolve<DataSourceManager>(new NamedParameter("name", "STONE刘先生"));
Console.WriteLine(manager.GetData());
Console.ReadLine();
}看到了吗?container.Resolve<DataSourceManager>()这里通过Resolve解析DataSourceManager实例,对于DataSourceManager类型,我们为Autofac提供了类型, 但是当Autofac创建DataSourceManager的实例, 调用它的构造函数的时候,它的构造函数需要提供一个IDataSource的实例作为参数的,Autofac会在自己的容器里,找注册过IDataSource的实例,并且通过AsImplementedInterfaces()方法,指明为接口IDataSource提供的实例。然后作为创建DataSourceManager时,提供给构造函数的参数。这整个原理不知道这样讲你能听懂吗?
大家上面提出的如果不用RegisterControllers来,需要手动添加怎么做?答案就是要写若干个这个方法。
builder.RegisterType<DefaultController>().InstancePerDependency();注:DefaultController 控制器的名称,你可要试着把RegisterControllers删除掉,用上面的这句来尝试一下。但是实际的项目中最好是用RegisterControllers。2、如果没有写builder.RegisterControllers<> ,而且控制器也没有通过builder.RegisterType<>注册, 你会看到如下的错误
整个MVC 使用autofac配置的工作就完成了。那接下来直接来看代码里面怎么使用。
2、 添加控制器,并注入依赖代码
public class DefaultController : Controller
{ IDataSource ds;
// 接口定义 构造函数注入
public DefaultController(IDataSource _ds)
{
ds = _ds;
} // GET: Default
public ActionResult Index()
{
//调用具体类的具体方法返回结果 赋值给ViewBag.Message
ViewBag.Message = "STONE刘先生:" + ds.GetData();
return View();
}
}整个功能请求的数据添加到ViewBag然后在页面上面显示出来,也比较简单的。
运行后的效果:
成功了!
补充一下:
上面的列子演示的是构造函数注入,那看看能否改成属性注入。
看如下代码,IDataSource 加上get;set就变成属性了:
public class DefaultController : Controller
{ public IDataSource ds { get; set; }
// 接口定义 构造函数注入
//public DefaultController(IDataSource _ds)
//{
// ds = _ds;
//} // GET: Default
public ActionResult Index()
{
//调用具体类的具体方法返回结果 赋值给ViewBag.Message
ViewBag.Message = "STONE刘先生:" + ds.GetData();
return View();
}
}如果现在任何地方都不改的情况下,你看看会报什么错,是不是提醒ds为null,那怎么支持属性注入呢! 我看了好久
builder.RegisterControllers(Assembly.GetExecutingAssembly()).PropertiesAutowired();把Global.asax里面的这句改成如上这句 就好了!
补充,自动注入
Autofac提供一个RegisterAssemblyTypes方法。它会去扫描所有的dll并把每个类注册为它所实现的接口。既然能够自动注入,那么接口和类的定义一定要有一定的规律。我们可以定义IDependency接口的类型,其他任何的接口都需要继承这个接口。比如
public interface IDependency
{
}
1
2
3
4
5
6
7
8
|
/// <summary> /// 业务逻辑实现——岗位管理 /// </summary> public class PostService : IDependency { public IPostService postService { get ; set ; } ........ } |
自动注入原理说明:
首先我们去找到所有Dll,再去找到实现了IDependency接口的类,然后使用RegisterAssemblyTypes进行注入。
![](https://common.cnblogs.com/images/copycode.gif)
Assembly[] assemblies = Directory.GetFiles(AppDomain.CurrentDomain.RelativeSearchPath, "*.dll").Select(Assembly.LoadFrom).ToArray();
//注册所有实现了 IDependency 接口的类型
Type baseType = typeof(IDependency);
builder.RegisterAssemblyTypes(assemblies)
.Where(type => baseType.IsAssignableFrom(type) && !type.IsAbstract)
.AsSelf().AsImplementedInterfaces()
.PropertiesAutowired().InstancePerLifetimeScope(); //注册MVC类型
builder.RegisterControllers(assemblies).PropertiesAutowired();
builder.RegisterFilterProvider(); var container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
![](https://common.cnblogs.com/images/copycode.gif)
作者:STONE刘先生 出处:http://www.cnblogs.com/liupeng/
转载:https://www.cnblogs.com/liupeng/p/4806184.html
本文版权归作者和博客园共有,欢迎转载。未经作者同意下,必须在文章页面明显标出原文链接及作者,否则保留追究法律责任的权利。
如果您认为这篇文章还不错或者有所收获,可以点击右下角的【推荐】按钮,因为你的支持是我继续写作,分享的最大动力!
IOC-AutoFac的更多相关文章
- 在asp.net web api 2 (ioc autofac) 使用 Serilog 记录日志
Serilog是.net里面非常不错的记录日志的库,另外一个我认为比较好的Log库是NLog. 在我个人的asp.net web api 2 基础框架(Github地址)里,我原来使用的是NLog,但 ...
- 开源项目 08 IOC Autofac
using Autofac; using System; using System.Collections.Generic; using System.Linq; using System.Text; ...
- Ioc Autofac心得
对于这个容器注入,个人也不是很熟悉,很多还不懂,只会基本的操作,几天把它记录下来,说不定以后帮助就大了呢,这方面跟安卓差距还是挺大的 下面记录下应用的流程 步骤: 1.添加应用 2.重写工厂(这里讲的 ...
- ioc autofac简单示例
1.winform用法: nuget安装autofac public interface ILog { bool Log(string msg); } public class TXTLogger : ...
- asp.net core 四 IOC&DI Autofac
其实关于IOC,DI已经有了很多的文章,但是自己在使用中还是有很多困惑,而且相信自己使用下,印象还是会比较深刻的 关于这段时间一直在学习.net core,但是这篇文章是比较重要的,也是我自己觉得学习 ...
- IOC容器-Autofac在MVC中实现json方式注入使用
在你阅读时,默认已经了解IOC和autofac的基本用法, 我在最近的我的博客项目中运用了IOC autofac 实现了依赖注入 由于我的项目时asp.net MVC所以我目前向大家展示MVC中如何使 ...
- Topshelf的Ioc实现
在前面使用Topshelf的文章里,我们的工作类TownCrier使用的是无参数的构造函数,满足测试的目的.在实际的开发过程中,我们常常需要使用带有参数的构造函数,就不可避免的使用Ioc的技术.在这里 ...
- autofac初识
在开始autofac时,有必要先了解两个关键词:“控制反转(IoC/Inverse Of Control)”与“依赖注入(DI/Dependence injection)”. 控制反转(IoC):它把 ...
- never下ioc
生命周期 当前分单例,作用域(范围),短暂.单例是整个服务中只有一个实例,短暂则是每一次得到的都是新的实例,作用域就是在该一套行动中内得到的是同一个实例,该行动中指的是什么?我们看看demo下的sta ...
- .Net 跨平台可移植类库正在进行
[原文发表地址] Cross-Platform Portable Class Libraries with .NET are Happening [译文发表地址] .Net 跨平台可移植类库正在进行 ...
随机推荐
- python文件操作各种模式和常用方法总结r r+ rb r+b
1.读,r r+ rb r+b read() 全部读取 read(n) 读取一部分 r模式下:n 个字符. rb模式下:n个 字节. readline() 按行读取. readlines() 返回个列 ...
- Bzoj1835:[ZJOI2010]基站选址
Sol 设\(f[i][j]\)表示钦定\(i\)建基站,建了\(j\)个基站的最小代价 \(f[i][j]=max(f[l][j-1]+\Sigma_{t=l+1}^{i-1}\)不能影响到的村庄的 ...
- 1004. 填充矩形 (Standard IO)
题目描述 已知矩形的大小为n×m,现用a×a的正方形填充该矩形.输入三个正整数n,m,a(n,m,a≤10^9),计算至多能填入多少正方形?(正方形可以正好碰到矩形边界,但不能超出矩形外) 输入 一行 ...
- inline-block元素,在同一行上下显示
两个元素使用了inline-block,并列显示时,会上下显示,给人感觉不在同一行 原因:其中一个元素使用了overflow:hidden,导致了基线变更 解决:1.另一个元素也添加overflow: ...
- js event事件对象概括
事件是用户或者浏览器自身执行的动作,而响应某个事件的函数就叫做事件处理程序或者叫事件侦听器. 定义事件处理程序可以大致分为以下三种: 一.html事件处理程序 元素支持的每种事件都可以用一个与之对应的 ...
- 向Github提交更改的代码
更改了本地的某一文件的代码,那么如何覆盖Github上的同一文件代码呢?请看以下步骤: 1.先用 git status 看你更改了哪些文件: 2.然后 git add 你想要提交的更改的文件 或者 g ...
- LINQ学习笔记(一)基本语法
1.LINQ简介 LINQ是Language Integrated Query的简称,它是集成在.NET编程语言中的一种特性.包括五个部分:LINQ to Objects.LINQ to DataSe ...
- QT网络编程UDP下C/S架构广播通信
QT有封装好的UDP协议的类,QUdpSocket,里面有我们想要的函数接口.感兴趣的话,可以看看. 先搞服务端吧,写一个子类,继承QDialog类,起名为UdpServer类.头文件要引用我们上边说 ...
- Hadoop学习---Hadoop的MapReduce的原理
MapReduce的原理 MapReduce的原理 NameNode:存放文件的元数据信息 DataNode:存放文件的具体内容 ResourceManager:资源管理,管理内存.CPU等 Node ...
- 如何跟踪比特币SV(BSV)地址余额?
Coin Balance Tracker 能够查看任何BSV/BCH/BTC地址的当前余额.您只需要确保你的电脑能连接Internet以及地址正确.此程序非常安全,因为它只使用公共数据,不需要登录和密 ...