據說.net 世界裡,最強的依賴注入容器是Autofac 。不管是誰,Nopcommerce2.8 用了它,是以就簡單研究一下喽。
用vs 2012 建立一個Asp.net mvc3 的樣例項目。然後使用NuGet(Vs2012 自帶的有,版本低的話,似乎要安裝插件),下載下傳安裝autofac的dll,如圖1,2.
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsISPrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdsATOfd3bkFGazxCMx8VesATMfhHLlN3XnxCMwEzX0xiRGZkRGZ0Xy9GbvNGLpZTY1EmMZVDUSFTU4VFRR9Fd4VGdsYTMfVmepNHLrJXYtJXZ0F2dvwVZnFWbp1zczV2YvJHctM3cv1Ce-cmbw5iYxMDNjhDZwMjN3QmN5ATZyI2M2EDO2QWOjJmN0QDNy8CXxMzLcdDMxIDMy8CXn9Gbi9CXzV2Zh1WavwVbvNmLvR3YxUjLzM3Lc9CX6MHc0RHaiojIsJye.png)
圖2 ,load autofac
autofac 要加載兩個dll哦,一個是autofac 的core ,另外一個是和asp.net mvc3內建的dll
然後,我建立一個實體資料模型,連結我的資料庫,加載Customer這個我已經建好的表,字段随意,資料随意。實體類Customer自動生成。加一個集合類,裝customer,
public class LCust
{
public List<Customer> clist;
}
接下來是一個ICusotmer接口和一個它的實作CustomerService:
public interface ICustomer
{
List<Customer>GetCustomers( );
}
public class CustomerService : ICustomer
{
public List<Customer>GetCustomers()
{
return new SeendioEntities().T_Adv_Customer.ToList();
}
}
好,準備工作就緒,開始依賴注入了。
在Gloabal.ascx檔案中:
using Autofac;
using Autofac.Builder;
using Autofac.Integration.Mvc;
下面是編輯Application_Start()方法,對ICustomer進行依賴注入:
|
在HomeController.cs中,修改構造函數:
private ICustomer _icustomer;
public HomeController(ICustomer customerservice)
{
_icustomer = customerservice;
}
修改action:
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傳回給視圖
}
在index.cshtml 中顯示Customer清單中每一個customer的email:
@model MvcApplication2.LCust
@{
ViewBag.Title = "首頁";
}
<ul>
@foreach (var item in Model.clist)
{
<li>@item.Email</li>
}
</ul>
運作,發現報了錯:
解決這個問題的方法似乎不少,我翻了翻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的東西
點選安裝。
将AuthoryManage.AutofacRegister 也引入Autofac包
導入成功之後,我先在AuthoryManage.InterfaceRepository這個類庫中添加一個接口,
接口
然後在AuthoryManage.Repository中分别加入下面這些類
下面是代碼:
public class BaseRepository :IBaseRepository{
public string GetData() {
return "這裡是MsSql";
}
}
public class BaseRepository : IBaseRepository {
public string GetData() {
return "這裡是MySql";
}
}
public class BaseRepository : IBaseRepository {
public string GetData() {
return "這裡是Oracle";
}
}
記得添加對AuthoryManage.InterfaceRepository的引用。
接下來寫下Service層的代碼
public interface IBaseService {
string GetData();
}
public interface IBaseService {
string GetData();
}
最值得注意的Service實作類代碼,請看:
public class BaseService:IBaseService {
private readonly IBaseRepository _repository;
public BaseService(IBaseRepository repository) {
this._repository = repository;
}
public string GetData() {
return _repository.GetData();
}
}
這是建好之後的Service層結構
也要記得引用對應DLL,那麼接下來就看看控制器這邊怎麼寫吧。
我就簡單先建立一個Home控制器吧。
并添加對service的引用。
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();
}
}
視圖代碼如下:
@{
ViewBag.Title = "Index";
}
<h2>@ViewBag.SSSS</h2>
接下來就去Global中實作我們的注入:
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));
}
}
}
要記住,在反射程式集的時候你要引用相對應的程式集。然後我們在運作一下程式來看下界面效果:
我們把global.asax裡面的代碼更改下,改成對Oracle的程式集注冊,
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));
}
}
}
看下運作效果:
需要注意的是我們需要引用下AuthoryManage.OracleRepository這個dll引用,那麼就是說我實作的方法更改了 我UI層也要去改動對應的引用。
閱讀目錄
- Mvc中使用Autofac
- 第一步:在mvc中添加dll檔案,可以通過Nuget直接添加
- 第二步:在App_Start檔案夾中添加一個AutofacConfig類
- 第三步:在Global.asax調用AutofacConfig類中的Register方法,注冊元件
- 第四步:簡單測試
回到頂部
Mvc中使用Autofac
前面學習了AutoFac的注冊、解析、生命周期,這裡寫一個AutoFac在ASP.NET MVC中的簡單使用。
基本結構:AutoFacMvc作為ui層 ,IService類庫(各種服務接口),Service類庫(IService中接口的實作),Model類庫(資料模型,這裡使用EF)
我們的目的:實作MVC中的Controller和Service中的具體實作類解耦
擷取使用者清單的簡單例子:
IService中的接口:
namespace IService
{
public interface IUserInfoService
{
List<UserInfo> GetUsers();
}
}
Service中的實作:
namespace Service
{
public class UserInfoService : IUserInfoService
{
//擷取使用者清單
public List<Model.UserInfo> GetUsers()
{
DbContext context = DbFactory.GetDbContext();
return context.Set<UserInfo>().ToList<UserInfo>();
}
}
}
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 }
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 }
UserInfoController :
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 }
View
@{
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>
運作結果:
補充:可以逐個進行注冊代碼如下,在Application_Start方法中添加如下代碼 :
//建立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));