据说.net 世界里,最强的依赖注入容器是Autofac 。不管是谁,Nopcommerce2.8 用了它,所以就简单研究一下喽。

          用vs 2012 创建一个Asp.net mvc3 的样例项目。然后使用NuGet(Vs2012 自带的有,版本低的话,似乎要安装插件),下载安装autofac的dll,如图1,2.

        在asp.net mvc 中使用Autofac_autofac       

                              图1 NuGet

在asp.net mvc 中使用Autofac_autofac_02

                  图2 ,load  autofac

autofac 要加载两个dll哦,一个是autofac 的core ,另外一个是和asp.net mvc3集成的dll

然后,我新建一个实体数据模型,链接我的数据库,加载Customer这个我已经建好的表,字段随意,数据随意。实体类Customer自动生成。加一个集合类,装customer,



public class LCust
{
  public List<Customer> clist;
}


 

接下来是一个ICusotmer接口和一个它的实现CustomerService:



在asp.net mvc 中使用Autofac_bundle_03

public interface ICustomer
{
List<Customer>GetCustomers( );
}
public class CustomerService : ICustomer
{

public List<Customer>GetCustomers()
{

return new SeendioEntities().T_Adv_Customer.ToList();
}
}


在asp.net mvc 中使用Autofac_bundle_03


 好,准备工作就绪,开始依赖注入了。

在Gloabal.ascx文件中:



using Autofac;
using Autofac.Builder;
using Autofac.Integration.Mvc;


 

下面是编辑Application_Start()方法,对ICustomer进行依赖注入:





​var​​ ​​builder = ​​​​new​​ ​​ContainerBuilder();​


​builder.RegisterType<CustomerService>().As<ICustomer>();​



 

在HomeController.cs中,修改构造函数:



private ICustomer _icustomer;
public HomeController(ICustomer customerservice)
{
_icustomer = customerservice;

}


修改action:



在asp.net mvc 中使用Autofac_bundle_03

public ActionResult Index( )
{
ViewBag.Message = "欢迎使用 ASP.NET MVC!";
List<Customer> clist = _icustomer.GetCustomers();//调用借口方法,获取所有的Customer
LCust c = new LCust();
c.clist = clist;
return View(c); //把Customer返回给视图
}


在asp.net mvc 中使用Autofac_bundle_03


在index.cshtml 中显示Customer列表中每一个customer的email:



在asp.net mvc 中使用Autofac_bundle_03

@model MvcApplication2.LCust

@{
ViewBag.Title = "主页";
}
<ul>
@foreach (var item in Model.clist)
{
<li>@item.Email</li>
}
</ul>


在asp.net mvc 中使用Autofac_bundle_03


运行,发现报了错:

在asp.net mvc 中使用Autofac_依赖注入_09

 

 解决这个问题的方法似乎不少,我翻了翻Nopcommerce 2.8的代码,发现了这么一个方法:RegisterControllers

于是在Application_Start()方法加上一句,对Controller进行依赖注入

 builder.RegisterControllers(Assembly.GetExecutingAssembly());

问题解决,运行出结果。

 

Autofac 粗浅的用还简单,但是在Nopcommerce2.8里,我看到了对它进行封装的代码,好纠结。

 

 Autofac是传说中速度最快的一套.NET高效的依赖注入框架。Autofac的介绍与使用请去参考​​Autofac全面解析系列(版本:3.5)。   这里介绍的已经挺详细的啦。​

      下面我就先来说说MVC4中使用Autofac吧,至于工厂模式与依赖注入的区别的话,这个我简单的解释一下,也只是我的个人观点。使用依赖注入最主要的就是为了解耦,当然工厂模式也可以实现实现大部分的解耦,这个是毋庸置疑的。工厂模式实现方式是向客户端提供一个接口,使客户端不要指定具体产品对象,创建多个产品族的产品对象。将具体实例的创建延迟到对应实现的子类中。但是当我们每次要去拿这个接口的时候就要通过这个工厂来拿了,那么就是说虽然我们排除了对实现接口的具体的方法的依赖,但是我们对工厂模式产生接口的方式产生了依赖。那么依赖注入就可以解决这个依赖了。我们在使用接口的时候可以完全的不需要考虑去取这个接口然后再继续使用接口。我们只要直接拿接口来用就可以了。这就是我个人对工厂模式和依赖注入的解释了,是不是把你们给搞混淆了。

  下面我就在MVC4中使用下Autofac吧。首先我们要先去NuGet下载一个Autofac MVC4的东西

在asp.net mvc 中使用Autofac_程序集_10

在asp.net mvc 中使用Autofac_依赖注入_11

点击安装。

将AuthoryManage.AutofacRegister 也引入Autofac包在asp.net mvc 中使用Autofac_autofac_12

导入成功之后,我先在AuthoryManage.InterfaceRepository这个类库中添加一个接口,在asp.net mvc 中使用Autofac_bundle_13


在asp.net mvc 中使用Autofac_bundle_14 接口


然后在AuthoryManage.Repository中分别加入下面这些类在asp.net mvc 中使用Autofac_程序集_15

下面是代码:


在asp.net mvc 中使用Autofac_程序集_16


public class BaseRepository :IBaseRepository{
public string GetData() {
return "这里是MsSql";
}
}


在asp.net mvc 中使用Autofac_程序集_16


public class BaseRepository : IBaseRepository {
public string GetData() {
return "这里是MySql";
}
}


在asp.net mvc 中使用Autofac_程序集_16


public class BaseRepository : IBaseRepository {
public string GetData() {
return "这里是Oracle";
}
}


记得添加对AuthoryManage.InterfaceRepository的引用。

接下来写下Service层的代码


在asp.net mvc 中使用Autofac_程序集_16


public interface IBaseService {
string GetData();
}


在asp.net mvc 中使用Autofac_程序集_16


public interface IBaseService {
string GetData();
}


 


最值得注意的Service实现类代码,请看:


在asp.net mvc 中使用Autofac_程序集_16


在asp.net mvc 中使用Autofac_bundle_03

public class BaseService:IBaseService {
private readonly IBaseRepository _repository;
public BaseService(IBaseRepository repository) {
this._repository = repository;
}
public string GetData() {
return _repository.GetData();
}
}


在asp.net mvc 中使用Autofac_bundle_03


这是建好之后的Service层结构

在asp.net mvc 中使用Autofac_bundle_24

也要记得引用对应DLL,那么接下来就看看控制器这边怎么写吧。

我就简单先建立一个Home控制器吧。在asp.net mvc 中使用Autofac_autofac_25并添加对service的引用。


在asp.net mvc 中使用Autofac_程序集_16


在asp.net mvc 中使用Autofac_bundle_03

public class HomeController : Controller {
//
// GET: /Home/
private IBaseService _service;
public HomeController(IBaseService service) {
this._service = service;
}
public ActionResult Index() {
ViewBag.SSSS = _service.GetData();
return View();
}

}


在asp.net mvc 中使用Autofac_bundle_03


视图代码如下:



在asp.net mvc 中使用Autofac_程序集_16


@{
ViewBag.Title = "Index";
}

<h2>@ViewBag.SSSS</h2>


 


接下来就去Global中实现我们的注入:

 


在asp.net mvc 中使用Autofac_程序集_16


在asp.net mvc 中使用Autofac_bundle_03

using Autofac;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Autofac.Integration.Mvc;
using System.Web;
using System.Web.Http;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;

namespace AuthoryManage.Web {
// 注意: 有关启用 IIS6 或 IIS7 经典模式的说明,
// 请访问 http://go.microsoft.com/?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);


var builder = new ContainerBuilder();
var assembly = Assembly.GetExecutingAssembly();
var repository = System.Reflection.Assembly.Load("AuthoryManage.MsSqlRepository");
builder.RegisterAssemblyTypes(repository, repository)
.AsImplementedInterfaces();
var service = System.Reflection.Assembly.Load("AuthoryManage.Service");
builder.RegisterAssemblyTypes(service, service)
.AsImplementedInterfaces();
builder.RegisterControllers(typeof(MvcApplication).Assembly);
//容器
var container = builder.Build();
//注入改为Autofac注入
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
}
}
}


在asp.net mvc 中使用Autofac_bundle_03


要记住,在反射程序集的时候你要引用相对应的程序集。然后我们在运行一下程序来看下界面效果:在asp.net mvc 中使用Autofac_bundle_33

我们把global.asax里面的代码更改下,改成对Oracle的程序集注册,


在asp.net mvc 中使用Autofac_程序集_16


在asp.net mvc 中使用Autofac_bundle_03

using Autofac;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Autofac.Integration.Mvc;
using System.Web;
using System.Web.Http;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;

namespace AuthoryManage.Web {
// 注意: 有关启用 IIS6 或 IIS7 经典模式的说明,
// 请访问 http://go.microsoft.com/?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);


var builder = new ContainerBuilder();
var assembly = Assembly.GetExecutingAssembly();
var repository = System.Reflection.Assembly.Load("AuthoryManage.OracleRepository");
builder.RegisterAssemblyTypes(repository, repository)
.AsImplementedInterfaces();
var service = System.Reflection.Assembly.Load("AuthoryManage.Service");
builder.RegisterAssemblyTypes(service, service)
.AsImplementedInterfaces();
builder.RegisterControllers(typeof(MvcApplication).Assembly);
//容器
var container = builder.Build();
//注入改为Autofac注入
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
}
}
}


在asp.net mvc 中使用Autofac_bundle_03


看下运行效果:在asp.net mvc 中使用Autofac_bundle_37

需要注意的是我们需要引用下AuthoryManage.OracleRepository这个dll引用,那么就是说我实现的方法更改了 我UI层也要去改动对应的引用。

 

 



阅读目录


 



​回到顶部​


Mvc中使用Autofac

前面学习了AutoFac的注册、解析、生命周期,这里写一个AutoFac在ASP.NET MVC中的简单使用。

基本结构:AutoFacMvc作为ui层 ,IService类库(各种服务接口),Service类库(IService中接口的实现),Model类库(数据模型,这里使用EF)

我们的目的:实现MVC中的Controller和Service中的具体实现类解耦

在asp.net mvc 中使用Autofac_mvc_38

获取用户列表的简单例子:

IService中的接口:



在asp.net mvc 中使用Autofac_bundle_03

namespace IService
{
public interface IUserInfoService
{
List<UserInfo> GetUsers();
}
}


在asp.net mvc 中使用Autofac_bundle_03


Service中的实现:



在asp.net mvc 中使用Autofac_bundle_03

namespace Service
{
public class UserInfoService : IUserInfoService
{
//获取用户列表
public List<Model.UserInfo> GetUsers()
{
DbContext context = DbFactory.GetDbContext();
return context.Set<UserInfo>().ToList<UserInfo>();
}
}
}


在asp.net mvc 中使用Autofac_bundle_03


 

第一步:在mvc中添加dll文件,可以通过Nuget直接添加

在asp.net mvc 中使用Autofac_autofac_43

第二步:在App_Start文件夹中添加一个AutofacConfig类



在asp.net mvc 中使用Autofac_bundle_03

1     public class AutofacConfig
2 {
3 /// <summary>
4 /// 负责调用autofac框架实现业务逻辑层和数据仓储层程序集中的类型对象的创建
5 /// 负责创建MVC控制器类的对象(调用控制器中的有参构造函数),接管DefaultControllerFactory的工作
6 /// </summary>
7 public static void Register()
8 {
9 //实例化一个autofac的创建容器
10 var builder = new ContainerBuilder();
11 //告诉Autofac框架,将来要创建的控制器类存放在哪个程序集 (AutoFacMvcDemo)
12 Assembly controllerAss = Assembly.Load("AutoFacMvcDemo");
13 builder.RegisterControllers(controllerAss);
14
15 //如果有Dal层的话,注册Dal层的组件
16 //告诉autofac框架注册数据仓储层所在程序集中的所有类的对象实例
17 //Assembly dalAss = Assembly.Load("Dal");
18 //创建respAss中的所有类的instance以此类的实现接口存储
19 //builder.RegisterTypes(dalAss.GetTypes()).AsImplementedInterfaces();
20
21 //告诉autofac框架注册业务逻辑层所在程序集中的所有类的对象实例
22 Assembly serviceAss = Assembly.Load("Service");
23 //创建serAss中的所有类的instance以此类的实现接口存储
24 builder.RegisterTypes(serviceAss.GetTypes()).AsImplementedInterfaces();
25
26
27 //创建一个Autofac的容器
28 var container = builder.Build();
29 //将MVC的控制器对象实例 交由autofac来创建
30 DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
31 }
32 }


在asp.net mvc 中使用Autofac_bundle_03


第三步:在Global.asax调用AutofacConfig类中的Register方法,注册组件



在asp.net mvc 中使用Autofac_bundle_03

1     public class MvcApplication : System.Web.HttpApplication
2 {
3 protected void Application_Start()
4 {
5 AreaRegistration.RegisterAllAreas();
6 RouteConfig.RegisterRoutes(RouteTable.Routes);
7 //注册组件
8 AutofacConfig.Register();
9 }
10 }


在asp.net mvc 中使用Autofac_bundle_03


第四步:简单测试

UserInfoController :



在asp.net mvc 中使用Autofac_bundle_03

1 namespace AutoFacMvcDemo.Controllers
2 {
3 public class UserInfoController : Controller
4 {
5 private IUserInfoService userinfoService;
6 //通过构造器注入依赖
7 public UserInfoController(IUserInfoService _userinfoService)
8 {
9 userinfoService = _userinfoService;
10 }
11
12 public ActionResult Index()
13 {
14 //不使用autofac时,service层和mvc ui层强耦合
15 //UserInfoService userInfoService = new UserInfoService();
16 //List<UserInfo> users= userInfoService.GetUsers();
17
18 List<UserInfo> users= userinfoService.GetUsers();
19 ViewBag.users = users;
20 return View();
21 }
22 }
23 }


在asp.net mvc 中使用Autofac_bundle_03


View



在asp.net mvc 中使用Autofac_bundle_03

@{
ViewBag.Title = "Index";
}
<h2>用户列表</h2>

@* 简单展示用户 *@
<table>
@foreach (var item in ViewBag.users)
{
<tr>
<td>@item.UId</td>
<td>@item.UserName</td>
<td>@item.Age</td>
</tr>
}
</table>


在asp.net mvc 中使用Autofac_bundle_03


运行结果:

在asp.net mvc 中使用Autofac_autofac_52


 

补充:可以逐个进行注册代码如下,在Application_Start方法中添加如下代码 :



在asp.net mvc 中使用Autofac_bundle_03

//创建autofac管理注册类的容器实例
var builder = new ContainerBuilder();
//注册组件(注意:在注册时添加了UserInfoService的引用,其实还是耦合的,在不分层的项目中好用)
builder.RegisterType<UserInfoService>().As<IUserInfoService>();
//使用Autofac提供的RegisterControllers扩展方法来对程序集中所有的Controller一次性的完成注册
builder.RegisterControllers(Assembly.GetExecutingAssembly());
//生成具体的实例
var container = builder.Build();
//下面就是使用MVC的扩展 更改了MVC中的注入方式.
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));


在asp.net mvc 中使用Autofac_bundle_03