一、前言
AutoFac是.NET平台下的一款著名的IoC Container,它可以讓我們很輕松的解除項目中服務類的接口與客戶類的接口實作類之間的依賴關系,進而降低系統各子產品之間耦合程度以提高系統的穩定性。最近在做畢業設計,在開發中采用了autofac來進行依賴注入,這裡是對踩到的一些坑的解決方法,希望可以給同樣不幸進入這些坑中的童鞋們提供一些解決思路。
對于IOC、DI相關的概念由于自己也是一知半解的,推薦T2噬菌體的這篇 依賴注入那些事兒 寫的很詳細也很好了解。
AutoFac文檔位址:http://autofac.readthedocs.io/en/latest/getting-started/index.html
使用AutoFac需要引用的類庫dll:Autofac.dll、Autofac.Configuration、Microsoft.Extensions.Configuration.Xml
PS:我是采用xml進行配置的AutoFac,如果你采用json進行配置,則需要引用Microsoft.Extensions.Configuration.Xml,使用nuget即可擷取到這些引用dll。
二、執行個體
項目結構如下圖所示,autofac涉及到類庫如下
PSU.Factory:autofac配置相關資訊
PSU.Domain:功能接口的實作類
PSU.IService:功能接口
PSU.Controllers:控制器
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIyZuBnL5gjN0MzMwcTMx0CN5MjM0gjM5EDMxEDM4EDMy0SO1gDMxMTMvwVMwgTMwIzLclTN4ATMzEzLcd2bsJ2Lc12bj5ycn9Gbi52YucTMwIzcldWYtl2Lc9CX6MHc0RHaiojIsJye.png)
PSU.IService、PSU.Domain就是基本的接口與其實作類,也就沒什麼東西了,測試的代碼如下:
1 //-----------------------------------------------------------------------
2 // <copyright file= "IIndex.cs">
3 // Copyright (c) Danvic712. All rights reserved.
4 // </copyright>
5 // Author: Danvic712
6 // Date Created: 2018/1/9 星期二 16:37:48
7 // Modified by:
8 // Description: 管理者首頁操作鄰域
9 //-----------------------------------------------------------------------
10 using PSU.Models.Area.Administrator.Home;
11 using System;
12 using System.Collections.Generic;
13 using System.Linq;
14 using System.Text;
15 using System.Threading.Tasks;
16
17 namespace PSU.IService.Area.Administrator.Home
18 {
19 public interface IIndex
20 {
21 /// <summary>
22 /// 頁面初始化加載
23 /// </summary>
24 /// <param name="webModel"></param>
25 /// <returns></returns>
26 IndexWebModel Init(IndexWebModel webModel);
27 }
28 }
接口定義
1 //-----------------------------------------------------------------------
2 // <copyright file= "IndexDomain.cs">
3 // Copyright (c) Danvic712. All rights reserved.
4 // </copyright>
5 // Author: Danvic712
6 // Date Created: 2018/1/9 星期二 16:42:53
7 // Modified by:
8 // Description: 管理者首頁操作鄰域接口實作
9 //-----------------------------------------------------------------------
10 using PSU.IService.Area.Administrator.Home;
11 using PSU.Models.Area.Administrator.Home;
12 using System;
13
14 namespace PSU.Domain.Area.Administrator.Home
15 {
16 public class IndexDomain : IIndex
17 {
18 /// <summary>
19 /// 頁面初始化加載
20 /// </summary>
21 /// <param name="webModel"></param>
22 /// <returns></returns>
23 public IndexWebModel Init(IndexWebModel webModel)
24 {
25 webModel = new IndexWebModel();
26 return webModel;
27 }
28 }
29 }
接口實作類
PSU.Factory這個類庫裡寫的是autofac的配置方法,在寫之前讓我們先看看官方的Demo:
簡單翻譯一下
- 你需要在你的項目裡加載Microsoft.Extensions.Configuration 這個dll,如果你使用json進行配置的話,你需要加載 Microsoft.Extensions.Configuration.Json 這個dll,而我是通過xml檔案進行配置,則需要加載 Microsoft.Extensions.Configuration.Xml
- 通過執行個體化ConfigurationBuilder來加載配置檔案
- 注冊配置元件
- 在容器中注冊配置子產品
因為我們會把所有的接口與實作類的映射放置于xml檔案中,将所有的子產品注冊在容器中,通過對于官方方法的封裝,建立一個靜态方法去自由的選擇加載需要接口與實作類,代碼和配置檔案如下:
1 //-----------------------------------------------------------------------
2 // <copyright file= "MAutoFac.cs">
3 // Copyright (c) Danvic712. All rights reserved.
4 // </copyright>
5 // Author: Danvic712
6 // Date Created: 2018/1/8 星期一 13:23:04
7 // Modified by:
8 // Description: AutoFac幫助類
9 //-----------------------------------------------------------------------
10 using Autofac;
11 using Autofac.Configuration;
12 using Microsoft.Extensions.Configuration;
13
14 namespace PSU.Factory
15 {
16 public class MAutoFac
17 {
18 /// <summary>
19 /// 緩存注冊容器
20 /// </summary>
21 private static IContainer _container = null;
22
23 /// <summary>
24 /// 注冊并建立執行個體
25 /// </summary>
26 /// <typeparam name="T"></typeparam>
27 /// <returns></returns>
28 public static T CreateInstance<T>()
29 {
30 if (_container == null)
31 {
32 var builder = new ContainerBuilder();
33
34 //讀取配置資訊
35 //
36 IConfigurationBuilder config = new ConfigurationBuilder();
37 config.AddXmlFile("autofac.config");
38
39 //注冊元件
40 var module = new ConfigurationModule(config.Build());
41
42 //注冊子產品
43 builder.RegisterModule(module);
44
45 _container = builder.Build();
46 }
47
48 return _container.Resolve<T>();
49 }
50 }
51 }
幫助類
1 <?xml version="1.0" encoding="utf-8" ?>
2 <autofac defaultAssembly="PSU.IService">
3 <!--Administrator:首頁接口-->
4 <components name="0">
5 <type>PSU.Domain.Area.Administrator.Home.IndexDomain,PSU.Domain</type>
6 <services name="0" type="PSU.IService.Area.Administrator.Home.IIndex" />
7 <injectProperties>true</injectProperties>
8 </components>
9 </autofac>
配置檔案
建立一個傳回類型是泛型的靜态方法,通過 Resolve<T>() 用來解析容器中已經注冊的執行個體T,并對給其進行指派,這樣,我們就可以通過傳入指定的接口來擷取對應的實作方法。
對于XML配置檔案,如果你是采用VS生成的配置檔案模版,你需要移除 configuration 根節點,直接使用 autofac 作為XML文檔的根節點,切記,否則你将無法讀取到配置資訊。同時,如果你是和我一樣的直接寫好配置檔案的位址,你需要将配置檔案放置在Web項目的根目錄下,或者顯示寫好加載的配置檔案的所在位址。
配置相關解釋:
1、defaultAssembly 預設的命名空間;如果type節點或者services節點的屬性type沒有設定類所在命名空間的話,将預設在defaultAssembly下查找類,type節點和services節點的屬性type設定格式為MyType,MyAssembly;
2、多個接口時添加多個components節點,name 屬性依次添加;
3、type節點對應接口實作類所在的位置(命名空間.類名,命名空間) --- 英文逗号;
4、services節點對應接口所在的位置(命名空間.接口類名)
5、injectProperties節點:是否啟用元件的屬性注入
在控制器調用接口執行個體,我是采用的重寫 Controller 類的 Inintalize 方法,實作接口的注入,這樣我們就可以在控制器中調用接口裡的方法了,實作方法如下圖所示。
1 //-----------------------------------------------------------------------
2 // <copyright file= "HomeController.cs">
3 // Copyright (c) Danvic712. All rights reserved.
4 // </copyright>
5 // Author: Danvic712
6 // Date Created: 2017/12/20 星期三 14:20:40
7 // Modified by:
8 // Description: Administrator-Home控制器
9 //-----------------------------------------------------------------------
10 using PSU.Factory;
11 using PSU.IService.Area.Administrator.Home;
12 using PSU.Models.Area.Administrator.Home;
13 using System.Web.Mvc;
14 using System.Web.Routing;
15
16 namespace PSU.Controllers.Areas.Administrator
17 {
18 public class HomeController : Controller
19 {
20 #region Initializes
21
22 private IIndex _iService;
23
24 protected override void Initialize(RequestContext requestContext)
25 {
26 base.Initialize(requestContext);
27
28 if (_iService == null)
29 {
30 _iService = MAutoFac.CreateInstance<IIndex>();
31 }
32 }
33
34 #endregion
35
36 #region Service
37
38 public ActionResult Index(IndexWebModel webModel)
39 {
40 _iService.Init(webModel);
41 return View(webModel);
42 }
43
44 #endregion
45 }
46 }
控制器
至此,我們要完成的也就差不多了,運作項目看看,咦,發現報錯,檢視報錯資訊,提示我們找不到PSU.Domain這個類庫dll
Web項目,它所依賴的dll全部位于網站根目錄下面的bin檔案夾中,由于我們采用IOC加載接口實作層,Web層隻引用接口,不引用接口實作層,是以autofac無法在項目中找到PSU.Domain這個dll,是以我們隻要把這個dll給移動到Web項目的bin目錄下面就可以了。編譯生成後手動移動,繁瑣、費事。這裡我采用的是通過在PSU.Domain這裡類庫的屬性上添加後期生成指令完成操作。重新生成下項目,預覽這個視圖頁面,bingo,可以了。
三、其它
1、通過屬性後期生成事件生成接口實作類庫到bin檔案夾裡,有人說在release模式下,執行失敗,我還沒到這一步,是以就不得而知了,解決方案可以見連結 =》https://social.msdn.microsoft.com/Forums/zh-CN/caf363ec-e0f9-41da-ad24-60993e83f190/releasebindll?forum=adonetzhchs
2、代碼完成之後,才發現AutoFac有專門的一個在MVC項目如何使用的執行個體,如果有童鞋用過的話,可以說說這兩種的優劣,示例見連結 =》http://autofac.readthedocs.io/en/latest/integration/mvc.html
3、個人的一點使用執行個體,希望對你有點用處,如果中間有說的不對的地方,歡迎指點
4、歡迎轉載,注明出處即可