一、前言
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:控制器
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、歡迎轉載,注明出處即可