1、前言
AutoFac是.NET平臺下的一款著名的IoC Container,它可讓咱們很輕鬆的解除項目中服務類的接口與客戶類的接口實現類之間的依賴關係,從而下降系統各模塊之間耦合程度以提升系統的穩定性。最近在作畢業設計,在開發中採用了autofac來進行依賴注入,這裏是對踩到的一些坑的解決方法,但願能夠給一樣不幸進入這些坑中的童鞋們提供一些解決思路。html
對於IOC、DI相關的概念因爲本身也是隻知其一;不知其二的,推薦T2噬菌體的這篇 依賴注入那些事兒 寫的很詳細也很好理解。web
AutoFac文檔地址:http://autofac.readthedocs.io/en/latest/getting-started/index.htmljson
使用AutoFac須要引用的類庫dll:Autofac.dll、Autofac.Configuration、Microsoft.Extensions.Configuration.Xml緩存
PS:我是採用xml進行配置的AutoFac,若是你採用json進行配置,則須要引用Microsoft.Extensions.Configuration.Xml,使用nuget便可獲取到這些引用dll。mvc
2、實例
項目結構以下圖所示,autofac涉及到類庫以下ide
PSU.Factory:autofac配置相關信息測試
PSU.Domain:功能接口的實現類網站
PSU.IService:功能接口ui
PSU.Controllers:控制器spa
PSU.IService、PSU.Domain就是基本的接口與其實現類,也就沒什麼東西了,測試的代碼以下:
![](http://static.javashuo.com/static/loading.gif)
![](http://static.javashuo.com/static/loading.gif)
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 }
![](http://static.javashuo.com/static/loading.gif)
![](http://static.javashuo.com/static/loading.gif)
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文件中,將全部的模塊註冊在容器中,經過對於官方方法的封裝,建立一個靜態方法去自由的選擇加載須要接口與實現類,代碼和配置文件以下:
![](http://static.javashuo.com/static/loading.gif)
![](http://static.javashuo.com/static/loading.gif)
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 }
![](http://static.javashuo.com/static/loading.gif)
![](http://static.javashuo.com/static/loading.gif)
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項目的根目錄下,或者顯示寫好加載的配置文件的所在地址。
配置相關解釋:
一、defaultAssembly 默認的命名空間;若是type節點或者services節點的屬性type沒有設置類所在命名空間的話,將默認在defaultAssembly下查找類,type節點和services節點的屬性type設置格式爲MyType,MyAssembly;
二、多個接口時添加多個components節點,name 屬性依次添加;
三、type節點對應接口實現類所在的位置(命名空間.類名,命名空間) --- 英文逗號;
四、services節點對應接口所在的位置(命名空間.接口類名)
五、injectProperties節點:是否啓用組件的屬性注入
在控制器調用接口實例,我是採用的重寫 Controller 類的 Inintalize 方法,實現接口的注入,這樣咱們就能夠在控制器中調用接口裏的方法了,實現方法以下圖所示。
![](http://static.javashuo.com/static/loading.gif)
![](http://static.javashuo.com/static/loading.gif)
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,能夠了。
3、其它
一、經過屬性後期生成事件生成接口實現類庫到bin文件夾裏,有人說在release模式下,執行失敗,我還沒到這一步,因此就不得而知了,解決方案能夠見連接 =》https://social.msdn.microsoft.com/Forums/zh-CN/caf363ec-e0f9-41da-ad24-60993e83f190/releasebindll?forum=adonetzhchs
二、代碼完成以後,才發現AutoFac有專門的一個在MVC項目如何使用的實例,若是有童鞋用過的話,能夠說說這兩種的優劣,示例見連接 =》http://autofac.readthedocs.io/en/latest/integration/mvc.html
三、我的的一點使用實例,但願對你有點用處,若是中間有說的不對的地方,歡迎指點
四、歡迎轉載,註明出處便可