autofac 方法注入注入到xml和config哪个好

AutoFac (控制反转IOC 与依赖注入DI)
先引入AutoFac 和AutoFac MVC两个程序集到项目中
然后我们在MVC(UI层)的App_Start文件夹下创建一个AutoFacConfig.cs类
using System.Collections.G
using System.L
using System.W
namespace FB.CMS.MSite.App_Start
using Autofac.Integration.M
using System.R
using System.Web.M
/// 这个类是我自己定义的一个类,主要用初始化AutoFac容器的相关数据
public class AutoFacConfig
public static void Register()
//初始化AutoFac的相关功能
1.0 告诉AutoFac初始化数据仓储层FB.CMS.Repository.dll中所有类的对象实例。这些对象实例以其接口的形式保存在AutoFac容器中
2.0 告诉AutoFac初始化业务逻辑层FB.CMS.Services.dll中所有类的对象实例。这些对象实例以其接口的形式保存在AutoFac容器中
3.0 将MVC默认的控制器工厂替换成AutoFac的工厂
//第一步: 构造一个AutoFac的builder容器
ContainerBuilder builder = new Autofac.ContainerBuilder();
//第二步:告诉AutoFac控制器工厂,控制器类的创建去哪些程序集中查找(默认控制器工厂是去扫描bin目录下的所有程序集)
//2.1 从当前运行的bin目录下加载FB.CMS.MvcSite.dll程序集
Assembly controllerAss = Assembly.Load("FB.CMS.MvcSite");
//2.2 告诉AutoFac控制器工厂,控制器的创建从controllerAss中查找(注意:RegisterControllers()方法是一个可变参数,如果你的控制器类的创建需要去多个程序集中查找的话,那么我们就再用Assembly controllerBss=Assembly.Load("需要的程序集名")加载需要的程序集,然后与controllerAss组成数组,然后将这个数组传递到RegisterControllers()方法中)
builder.RegisterControllers(controllerAss);
//第三步:告诉AutoFac容器,创建项目中的指定类的对象实例,以接口的形式存储(其实就是创建数据仓储层与业务逻辑层这两个程序集中所有类的对象实例,然后以其接口的形式保存到AutoFac容器内存中,当然如果有需要也可以创建其他程序集的所有类的对象实例,这个只需要我们指定就可以了)
//3.1 加载数据仓储层FB.CMS.Repository这个程序集。
Assembly repositoryAss = Assembly.Load("FB.CMS.Repository");
//3.2 反射扫描这个FB.CMS.Repository.dll程序集中所有的类,得到这个程序集中所有类的集合。
Type[] rtypes = repositoryAss.GetTypes();
//3.3 告诉AutoFac容器,创建rtypes这个集合中所有类的对象实例
builder.RegisterTypes(rtypes)
.AsImplementedInterfaces(); //指明创建的rtypes这个集合中所有类的对象实例,以其接口的形式保存
//3.4 加载业务逻辑层FB.CMS.Services这个程序集。
Assembly servicesAss = Assembly.Load("FB.CMS.Services");
//3.5 反射扫描这个FB.CMS.Services.dll程序集中所有的类,得到这个程序集中所有类的集合。
Type[] stypes = servicesAss.GetTypes();
//3.6 告诉AutoFac容器,创建stypes这个集合中所有类的对象实例
builder.RegisterTypes(stypes)
.AsImplementedInterfaces(); //指明创建的stypes这个集合中所有类的对象实例,以其接口的形式保存
//第四步:创建一个真正的AutoFac的工作容器
var container = builder.Build();
//我们已经创建了指定程序集的所有类的对象实例,并以其接口的形式保存在AutoFac容器内存中了。那么我们怎么去拿它呢?
//从AutoFac容器内部根据指定的接口获取其实现类的对象实例
//假设我要拿到IsysFunctionServices这个接口的实现类的对象实例,怎么拿呢?
//var obj = container.Resolve(); //只有有特殊需求的时候可以通过这样的形式来拿。一般情况下没有必要这样来拿,因为AutoFac会自动工作(即:会自动去类的带参数的构造函数中找与容器中key一致的参数类型,并将对象注入到类中,其实就是将对象赋值给构造函数的参数)
//第五步:将当前容器中的控制器工厂替换掉MVC默认的控制器工厂。(即:不要MVC默认的控制器工厂了,用AutoFac容器中的控制器工厂替代)此处使用的是将AutoFac工作容器交给MVC底层 (需要using System.Web.M)
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
//我们知道控制器的创建是调用MVC默认的控制器工厂,默认的控制器工厂是调用控制器类的无参构造函数
//可是我们如果要使用AutoFac自动工厂,将对象通过构造函数注入类中,那么这个构造函数就需要带参数
//如果我们将控制器的无参构造函数删除,保留带参数的构造函数,MVC默认的控制器工厂来创建控制的时候
//就会去调用无参的构造函数,可是这时候发现没有无参的构造函数于是就报“没有为该对象定义无参数的构造函数”错误
//既然报错,那我们如果保留无参的构造函数,同时在声明一个带参数的构造函数是否可行呢?
//答案;行是行,但是创建控制器的时候,MVC默认的控制器工厂调用的是无参构造函数,它并不会去调用有参的构造函数
//这时候,我们就只能将AutoFac它的控制器工厂替换调用MVC默认的控制器工厂(控制器由AutoFac的控制器工厂来创建)
//而AutoFac控制器工厂在创建控制的时候只会扫描带参数的构造函数,并将对象注入到带参数的构造函数中
//AutofacDependencyResolver这个控制器工厂是继承了 IDependencyResolver接口的,而IDependencyResolver接口是MVC的东西
//MVC默认的控制器工厂名字叫:DefaultControllerFactory
//具体参考:/artech/archive//controller-activation-032.
然后我们在Global.asax文件中的Application_Start()方法中来调用这个类
using FB.CMS.MvcSite.App_S
using System.Collections.G
using System.L
using System.W
using System.Web.H
using System.Web.M
using System.Web.O
using System.Web.R
namespace FB.CMS.MvcSite
// 注意: 有关启用 IIS6 或 IIS7 经典模式的说明,
// 请访问 /?LinkId=9394801
public class MvcApplication : System.Web.HttpApplication
protected void Application_Start()
AreaRegistration.RegisterAllAreas();
WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
//第一: 在网站一启动的时候就初始化AutoFac的相关功能
1.0 告诉AutoFac初始化数据仓储层FB.CMS.Repository.dll中所有类的对象实例。这些对象实例以其接口的形式保存在AutoFac容器中
2.0 告诉AutoFac初始化业务逻辑层FB.CMS.Services.dll中所有类的对象实例。这些对象实例以其接口的形式保存在AutoFac容器中
3.0 将MVC默认的控制器工厂替换成AutoFac的工厂
//具体做法就是我们去App_Start文件夹下创建一个AutoFacConfig类,具体实现什么功能去这个类中实现。然后再这里调用下这个类
AutoFacConfig.Register();
Home控制器
using System.Collections.G
using System.L
using System.W
using System.Web.M
namespace FB.CMS.MvcSite.Controllers
using FB.CMS.IS
public class HomeController : Controller
IsysFunctionS
public HomeController(IsysFunctionServices dal) //依赖构造函数进行对象注入
this.dal = //在构造函数中初始化HomeController控制器类的dal属性 (这个dal属性的类型是IsysFunctionServices)
public ActionResult Index()
var a = dal.QueryWhere(r => r.fID > 20).ToList(); //查询
return View();
(window.slotbydup=window.slotbydup || []).push({
id: '2467140',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467141',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467143',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467148',
container: s,
size: '1000,90',
display: 'inlay-fix'Autofac是一套高效的依赖注入框架。
Autofac官方网站:
Autofac在Github上的开源项目:
Autofac安装:通过VS的Nuget可以很方便的获取。
依赖注入,这个专业词我们可以分为两个部分来理解:
依赖,也就是UML中描述事物之间关系的依赖关系,依赖关系描述了事物A在某些情况下会使用到事物B,事物B的变化会影响到事物A;
注入,医生通过针头将药物注入到病人体内。注入也就是由外向内注入、灌输一些东西。
综合上面的说明,依赖注入就是A类依赖B类,B类的实例由外部向A注入,而不是由A自己进行实例化或初始化。
我们先理解构造器注入的字面意思,构造器注入也就表示,依赖关系通过构造器进行注入。
这种我们平时是非常常见的,类A依赖于类B,类A的构造方法中,有一个参数为类B,在new 类A,会从外部为类B传入实例,这就是构造注入:
class Program
static void Main(string[] args)
var b = new ();
var a = new (b);
private B _b;
public A(B b)
class B { }
上面说明了构造注入的含义以及构造注入的表现形式,下面我们来看看autofac中的构造注入。
还记得在上一篇博文 中的小结中提到了构造注入这个概念。在使用autofac时,构造注入是默认行为。
以上面的代码为例,如果类型A和类型B都注册到了autofac中,那么在通过autofac解析获取A时,autofac会检测到A的构造方法中是要一个参数B,而类型B是已经注册到autofac中的,所以autofac会自动创建b参数,然后传入A的构造方法中的。这样,autofac就自动帮我们完成了构造注入的工作。
class Program
static void Main(string[] args)
var builder = new ContainerBuilder();
builder.RegisterType&&();
builder.RegisterType&&();
var container = builder.Build();
var a = container.Resolve&&(); //A的构造方法需要参数b,但是这里不需要做更多地操作
private B _b;
public A(B b)
class B { }
属性注入也就是通过属性进行注入,我们修改上面的A类,将变量_b通过属性暴露出来,并且删掉有参构造方法,然后让我们看看我们平常写代码时怎么实现属性注入的:
class Program
static void Main(string[] args)
var a = new ();
//点击A查看A类修改后结构
var b = new ();
//通过属性来注入具有依赖关系的B
private B _b;
public B B
get { return _b; }
set { _b = }
class B { }
这种代码在日常中我们写过了无数遍,即使是这么平常的代码,但这就是属性注入。
但是有一点还是要注意的,我们不能随便把这种类似的代码拿出去就告诉别人,我们需要注意一点,需要分清两者之间是否真的是依赖关系。比如领域模型,简单的领域模型就是将数据表映射为一个类,对于数据表的每个字段,我们会生成一个对应的属性,对于这种,我们不能够在为每个属性进行赋值时就说&这是依赖注入&,这并不是依赖注入,更多情况下,字段与表的关系是一个组合关系。这一点对于之前的构造注入和后面会讲到的方法注入都适用。
说完注意点,让我们再来看看autofac是怎么进行属性注入的:
属性注入的所有注入方式都是在注册时定义的,不像构造注入那般,可以在Resolve时传参注入。
构造器注入是默认行为,不需要设置,默认会去检查,而属性注入并不是默认行为。但是我们可以通过设置,让属性注入也成为自动注入。
class Program
static void Main(string[] args)
var builder = new ContainerBuilder();
// 通过PropertiesAutowired制定类型A在获取时会自动注入A的属性
builder.RegisterType&&().PropertiesAutowired();
builder.RegisterType&&();
var container = builder.Build();
var a = container.Resolve&&();
Console.Write("Press any key to continue...");
Console.ReadKey();
使用PropertiesAutowired也只是能指定某个类会自动进行属性注入,没有一键设置所有类型都会自动注入属性的设置。而且还需要注意一点,设置了自动属性注入后,也不代表所有属性都会自动注入,只有注册到Autofac中的类型才能自动注入。
PropertiesAutowired方式会自动注入所有可以注入的属性,但是如果只想注入指定几个属性,可以使用除PropertiesAutowired以外的几种注入方式,WithProperty就是其中一种:
class Program
static void Main(string[] args)
var builder = new ContainerBuilder();
builder.RegisterType&&().WithProperty(new NamedPropertyParameter("B", new ()));
// builder.RegisterType&A&().WithProperty("B", new B());
//效果与上面相同var container = builder.Build();
var a = container.Resolve&&();
Console.Write("Press any key to continue...");
Console.ReadKey();
用法简单,WithProprtties的使用方式与WithProperty相似,在此就不贴代码了。
在注册篇里面有讲到一种方式,lambda注册时,因为是写lambda表达式进行注册,其lambda内容可以写很多,其中就可以进行属性注入:
var builder = new ContainerBuilder();
builder.Register(c =&
var _a = new ();
_a.B = new (); //手动注入
return _a;
这里的注入,就是最开始讲到属性注入时的那种赋值注入。
在autofac中,还有一些事件,这些事件在不同时期触发,事件相关的具体内容将在后续说明。在注入中能够使用到的事件有OnActivating和OnActivated,他们是在对象Resolve出来后触发,可以在事件中修改或替换返回对象,同样也可以进行属性注入:
var builder = new ContainerBuilder();
builder.RegisterType&&().OnActivating(e =&
e.Instance.B = new (); //Instance为Resolve出来的实例,类型为A
OnActivated事件的写法与OnActivating相同,关于两个事件的区别,将在后续博文中进行说明,请持续关注!
方法注入也不是默认行为,而且还没有提供像属性注入那样的自动注入设置。
方法注入有两种方式,也就是属性注入的后两种方式:lambda以及事件。大家应该已经能够想到注入的代码是什么样了:
var builder = new ContainerBuilder();
builder.Register(cc =&
var _a = new A();
_a.MethodInjection(new B());
return _a;
builder.RegisterType&A&().OnActivated(e =&
e.Instance.MethodInjection(new B());
MethodInjection为A的一个方法,并且它需要一个类型为B的参数,我们在外部通过方法的方式将B传入,这就是方法注入。这里需要特别贴一下A类型的代码,相对之前有所改动,不仅仅是添加了一个方法:
public void MethodInjection(B b)
// 做一些操作
这段代码可能与一些朋友想象中的不一样,有些朋友可能想着A中还有一个成员_b,然后在方法MethodInjection中将b赋值给_b。这里我特意将成员_b去掉,为的就是说明一个问题:
不是两个类型之间一定是成员关系,然后才能有依赖注入,我们得理解依赖的含义。A类型在某些操作中需要使用到B类型,而并不将B类型持久的保存起来,临时使用也是一种依赖关系。关于为什么这样就算作依赖注入,在我们了解刚刚说的依赖关系后,再来看看依赖的注入与不注入的不同形式,如果不是注入的方式,那么B类型将不做为参数传入,而直接在方法中new。
而依赖注入的好处,在这里还不能很好的看到,因为现在是在讲autofac中关于注入的方式。如果想更只管的看到注入的好处,我们将参数B换成接口IClass,使用注入的方式,我们在外部传入IClass的实例,因为IClass是接口,我们可以传入不同的实现,在更换实现时,这个方法内部的代码是不需要改动的,反之是需要改动的。依赖注入的好处,我们点到为止了,主要还是要在日常多使用对比,这样才能更切身的体会它的美妙之处!
关于注入这块儿,其实我个人有个疑问,关于autofac。属性注入中,我们可以通过设置PropertiesAutowired进行自动注入,但是有时,可能大部分属性我们都希望能够自动注入,然而有时会有那么几个属性我们需要自动注入忽略掉他们,在我想来,应该是有一个Attribute用于标记属性,被标记的属性会在属性自动注入时被忽略。
而我想的这种Attribute,我找了找,autofac中貌似并没看到。也可能是我自己忽略掉了,如果大家谁有知道的,烦请指导一下,谢谢
个人还是推荐使用默认最简单的构造注入,不需要传参的那种;属性注入推荐设置自动属性注入,如果能够找到疑问中说到的那种Attribute,那就更好了;方法注入还是不怎么推荐的。
其实这里的推荐原则是这样的,需要在注册时进行指定注入的方式实际是不太好的,因为后来的人可能不太清楚每个类型的注入规则,还需要到注册的地方进行查看,而且不同人员写的不同,这样容易混乱。而在获取时进行注入,实际也是不太妥的,因为在实际的用法中,我们会将注册类型与接口进行关联,在获取是直接获取接口类型。也正因为我们获取时获取的是接口类型,我们无法保证接口的实际实现是不是具有我们预期的参数。
如果有任何问题,还希望大家能够提出讨论,互相学习。也希望能够有前辈对博客的内容及表达方式提出意见和建议,谢谢!
阅读(...) 评论()游刃于MVC、WCF中的Autofac - ASP.NET技巧 - 大学IT网
当前位置: >
> 游刃于MVC、WCF中的Autofac
关键词:&&阅读(1945) 赞(10)
[摘要]本文是对游刃于MVC、WCF中的Autofac的讲解,对学习ASP.NET编程技术有所帮助,与大家分享。
为了程序的健壮性、扩展性、可维护性,依赖抽象而不是具体实现类等等,于是我选择了Autofac依赖注入容器 就是这个工厂来降低耦合。之前买东西是自己去超市,现在呢 我需要什么东西,他们给送过来直接拿到了。
本例中将会分享
1.Autofac在Mvc的Controller控制器、Filter过滤器的使用
2.WCF中的使用
3.用Autofac来完成Unit Of Work工作单元模式 即同一个界限上下文内可以共享同一个工作单元实例。这样就可以统一提交,起到事务作用、数据统一性。一个http请求只有一个上下文实例也算是性能优化吧, 在这里只用到工作单元的一些皮毛。
Demo全貌如下
Autofac.DataModel 采用database first的实体数据模型 Autofac.Repository实体泛型的仓储模式 ,也可以简单的理解是数据层 Autofac.CoreService 业务逻辑处理 Autofac.UnitOfWork 工作单元统一提交 Autofac.Controllers 控制器层是从Web层把所有控制器提取出来,这里用到区域Area AutoFac.Web 前端采用的是MVVM模式的knockout.js ,还有autofac的配置 Autofac.ViewModel 视图
  其中Repository、UnitOfWork、CoreService几者之间调用接口或对供其他层调用接口。
  从nuget获取必要的Autofac程序包 Autofac、Autofac.Configuration、Autofac.Integration.Mvc、Autofac.Integration.Wcf
各个层依赖的是接口而不是具体实现类,Autofac是个工厂可以通过编译的代码和xml配置文件两种方式指定接口、实现类来完成注入实例。
这里用的是xml配置的方式,需要用到Autofac.Configuration程序集。这样做有个明显的好处:文件不需要编译;不会扰乱各层关系。为什么这么说呢?如果用代码来完成,web层就需要其他层的接口和实现类 也就是引用Repository、UnitOfWork、CoreService层,很明显web层只需要引用Autofac.Controllers 就足够了。而通过xml配置文件可以在bin目录下找到具体的程序集如:Autofac.CoreService.dll
Autoface依赖注入在MVC里实现
Global.cs    protected void Application_Start()
//创建IOC容器
AutofacRegistion.BuildMvcContainer();
AutofacRegistion.BuildWcfContainer();
AreaRegistration.RegisterAllAreas();
WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
}/// &summary&
/// 依赖注入Controller、FilterAtrribute、WCF
/// &/summary&
public class AutofacRegistion
/// &summary&
/// 创建 MVC容器(包含Filter)
/// &/summary&
public static void BuildMvcContainer()
var builder = new ContainerBuilder();
//注册Module方法2 在Web.config中配制方式
builder.RegisterModule(new ConfigurationSettingsReader("autofacMvc"));
//加载 *.Controllers 层的控制器,否则无法在其他层控制器构造注入,只能在web层注入
Assembly[] asm = GetAllAssembly("*.Controllers.dll").ToArray();
builder.RegisterAssemblyTypes(asm);
//注册仓储
Assembly[] asmRepository = GetAllAssembly("*.Repository.dll").ToArray();
builder.RegisterAssemblyTypes(asmRepository)
.Where(t =& t.Name.EndsWith("Repository"))
.AsImplementedInterfaces();
builder.RegisterControllers(Assembly.GetExecutingAssembly());
builder.RegisterModelBinders(Assembly.GetExecutingAssembly());
builder.RegisterModelBinderProvider();
//注册过滤器
builder.RegisterFilterProvider();
builder.RegisterType&OperateAttribute&().PropertiesAutowired();
builder.RegisterControllers(typeof(MvcApplication).Assembly);
var container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
/// &summary&
///创建WCF的容器,不存放Controller、Filter
/// &/summary&
public static void BuildWcfContainer()
var builder = new ContainerBuilder();
builder.RegisterModule(new ConfigurationSettingsReader("autofacWcf"));
builder.RegisterModelBinders(Assembly.GetExecutingAssembly());
builder.RegisterModelBinderProvider();
var container = builder.Build();
//WCF IOC容器
AutofacHostFactory.Container =
//DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
#region 加载程序集
public static List&Assembly& GetAllAssembly(string dllName)
List&string& pluginpath = FindPlugin(dllName);
var list = new List&Assembly&();
foreach (string filename in pluginpath)
string asmname = Path.GetFileNameWithoutExtension(filename);
if (asmname != string.Empty)
Assembly asm = Assembly.LoadFrom(filename);
list.Add(asm);
catch (Exception ex)
Console.Write(ex.Message);
//查找所有插件的路径
private static List&string& FindPlugin(string dllName)
List&string& pluginpath = new List&string&();
string path = AppDomain.CurrentDomain.BaseD
string dir = bine(path, "bin");
string[] dllList = Directory.GetFiles(dir, dllName);
if (dllList.Length & 0)
pluginpath.AddRange(dllList.Select(item =& bine(dir, item.Substring(dir.Length + 1))));
#endregion
1 web.config还需要配置 globlal代码中对应的【autofacMvc】和【autofacWcf】节点
2 反射*.Controllers.dll获取Autofac.Controllers程序集,实现注入
3反射*.Repository.dll获取 Autofac.Repository程序集以'Repository'结尾的类的实例注入到它所继承的接口,这个就不需要在xml中配置
4filter的注入和controller的注入方式不一样
5 MVC和WCF注入实例分别存到两个容器中。这就用到Autofac.Integration.Mvc、Autofac.Integration.Wcf两个程序集。WCF注入的容器中不需要Controller、Filter,就可以把相关的反射和注册去掉了。
web.config&configSections&
&!-- autofac配置--&
&section name="autofacMvc" type="Autofac.Configuration.SectionHandler, Autofac.Configuration" /&
&section name="autofacWcf" type="Autofac.Configuration.SectionHandler, Autofac.Configuration" /&
&/configSections&
&autofacMvc&
&file name="configs/CoreService.config" section="autofac" /&
&/autofacMvc&
&autofacWcf&
&!--&file name="configs/IocDAL.config" section="autofac" /&--&
&/autofacWcf&
&!--↑↑↑↑autofac配置结束↑↑↑↑--&
在上述webconfig中为了统一管理配置,具体指定接口、实现类、和注入实例的生命周期放到了configs/CoreService.config文件中
CoreService.config&?xml version="1.0" encoding="utf-8"?&
&configuration&
&configSections&
&section name="autofac" type="Autofac.Configuration.SectionHandler, Autofac.Configuration"/&
&/configSections&
&components&
&!--DbContext上下文的生命周期为【per-lifetime-scope】即http请求的生命周期 --&
&component type="Autofac.DataModel.VehicleCheckDBEntities, Autofac.DataModel"
service="System.Data.Entity.DbContext, EntityFramework"
instance-scope="per-lifetime-scope"/&
&component type="Autofac.UnitOfWork.UnitOfWork, Autofac.UnitOfWork" service="Autofac.UnitOfWork.IUnitOfWork, Autofac.UnitOfWork" /&
&component type="Autofac.CoreService.Impl.UserManage, Autofac.CoreService" service="Autofac.CoreService.IUserManage, Autofac.CoreService" /&
&component type="Autofac.CoreService.Impl.RoleManage, Autofac.CoreService" service="Autofac.CoreService.IRoleManage, Autofac.CoreService" /&
&/components&
&/autofac&
&/configuration&
1component组件配置中type、service配置的是实现类、程序集名称(不是命名空间)、接口、程序集名称。
2instance-scope 配置的是实例的生命周期。本例中用到两种:一是默认的调用一次创建一次;二是一个http请求会共享一个实例,期间会多次用到,但只有一个实例。这个就是工作单元的核心了。instance-scope="per-lifetime-scope"类型共享DbContext的上下文实例。
参考官网http://docs.autofac.org/en/latest/configuration/xml.html#additional-config-files
MVC、WCF下是通过构造方法注入,Filter过滤器是通过访问器get set注入,下面有具体区别。
Controller和其他层的构造注入public class HomeController : Controller
private readonly IUserManage _userM
private IRoleManage _roleM
public HomeController(IUserManage userManage, IRoleManage roleManage)
_userManage = userM
_roleManage = roleM
Filter过滤器的注入取得实例public class OperateAttribute : ActionFilterAttribute
public IUserManage UserManage { }
public override void OnActionExecuted(ActionExecutedContext filterContext)
//Do Something...
var user =UserManage.LoadUser(0);
if (user == null)
filterContext.Result = new JsonResult
Data=new{message="不合法操作,未能进入"},
JsonRequestBehavior = JsonRequestBehavior.AllowGet
WCF注入&!-- wcf服务文件 --&
&%@ ServiceHost
Language="C#"
Debug="true"
Service="CypApp.VehicleWeb.Services.IAutofacService,CypApp.VehicleWeb"
Factory="Autofac.Integration.Wcf.AutofacServiceHostFactory, Autofac.Integration.Wcf"
//契约的实现类服务
/// &summary&
/// Autofac wcf注入
/// &/summary&
public class AutofacService : IAutofacService
private readonly IInspectorBc _functionBc;
//构造函数依赖注入
public AutofacService(IInspectorBc functionBc)
_functionBc = functionBc;
public void DoWork()
_functionBc.GetCompanyIdByInspectorId(0);
}/// &summary&
EntityFramework仓储操作基类
/// &/summary&
/// &typeparam name="TEntity"&动态实体类型&/typeparam&
public class EFRepositoryBase&TEntity& : IRepository&TEntity& where TEntity : class,new()
public EFRepositoryBase(DbContext context)
public DbContext Context { }
public void Dispose()
if (Context==null)
Context.Dispose();
GC.SuppressFinalize(this);
public IQueryable&TEntity& Entities()
return Context.Set&TEntity&().AsQueryable();
//Delete、Update等等
}public sealed class UnitOfWork : IUnitOfWork
/// &summary&
/// The DbContext
/// &/summary&
private DbContext _dbC
/// &summary&
/// Initializes a new instance of the UnitOfWork class.
/// &/summary&
/// &param name="context"&The object context&/param&
public UnitOfWork(DbContext context)
_dbContext =
/// &summary&
/// Saves all pending changes
/// &/summary&
/// &returns&The number of objects in an Added, Modified, or Deleted state&/returns&
public int Commit()
// Save changes with the default options
return _dbContext.SaveChanges();
/// &summary&
/// Disposes the current object
/// &/summary&
public void Dispose()
Dispose(true);
GC.SuppressFinalize(this);
/// &summary&
/// Disposes all external resources.
/// &/summary&
/// &param name="disposing"&The dispose indicator.&/param&
private void Dispose(bool disposing)
if (disposing)
if (_dbContext != null)
_dbContext.Dispose();
_dbContext =
}//业务逻辑处理public class UserManage : IUserManage
private readonly IUserRepository _userR
private readonly IUserRoleRepository _userRoleR
private IUnitOfWork _unitOfW
public UserManage(IUserRepository userRepository, IUserRoleRepository userRoleRepository,IUnitOfWork unitOfWork)
_userRepository = userR
_userRoleRepository = userRoleR
_unitOfWork = unitOfW
/// &summary&
/// 添加、修改 User
/// &/summary&
/// &param name="userModel"&&/param&
/// &param name="message"&&/param&
/// &returns&&/returns&
public bool SaveUser(UserModel userModel , out string message)
var userEntity = new Sys_User
UserName = userModel.UserName,
Password = userModel.Password,
UserTrueName = userModel.UserTrueName,
CreateDate = DateTime.Now,
//添加用户
if (userModel.Id & 1)
_userRepository.Insert(userEntity);
if (userEntity.Id & 1)
message = "添加用户失败";
//修改操作
//删除用户角色关系
var userRoleIdArray = _userRoleRepository.Entities()
.Where(m =& m.UserId == userModel.Id)
.Select(s =& s.Id).ToList();
foreach (var roleId in userRoleIdArray)
_userRoleRepository.Delete(new Sys_User_Roles {Id = roleId});
var userRoles = new List&Sys_User_Roles&();
foreach (var roleId in userModel.Role)
userRoles.Add(new Sys_User_Roles { UserId = userModel.Id, RoleId = roleId });
//添加用户角色关系
_userRoleRepository.Insert(userRoles);
_mit() & 0;
批量删除、批量添加操作只是映射,并未提交,只有Commit后才会保存数据。各个类拿到的DbContext是同一个实例,因此统一提交整个上下文状态才起到了作用。
仓储和工作单元都有销毁方法,每次调用仓储类和工作单元类, 都会从IOC容器取到共享实例Dbcontext,当处理完业务后会把这些拿到的Dbcontext实例销毁掉。
相关ASP.NET技巧推荐

我要回帖

更多关于 autofac 方法注入 的文章

 

随机推荐