ASP.NET MVC IOC依賴註入之Autofac系列(一)

来源:https://www.cnblogs.com/xyh9039/archive/2019/08/07/11318247.html
-Advertisement-
Play Games

本系列主要講述IOC依賴註入之Autofac在ASP.NET MVC項目中以及在WebForm項目中的具體應用。 ...


話不多說,直入主題看我們的解決方案結構:

分別對上面的工程進行簡單的說明:

1、TianYa.DotNetShare.Model:為demo的實體層

2、TianYa.DotNetShare.Repository:為demo的倉儲層即數據訪問層

3、TianYa.DotNetShare.Service:為demo的服務層即業務邏輯層

4、TianYa.DotNetShare.MvcDemo:為demo的web層項目,MVC框架

約定:本demo的web項目為ASP.NET Web 應用程式(.NET Framework 4.5) MVC框架,實體層、倉儲層、服務層均為.NET Framework 4.5 類庫。

一、實體層

1、定義一個空介面IDependency,後面有妙用,用於一次性註入

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TianYa.DotNetShare.Model
{
    /// <summary>
    /// 空介面,用於一次性註入
    /// </summary>
    public interface IDependency
    {
    }
}

2、新建一個學生實體 Student

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TianYa.DotNetShare.Model
{
    /// <summary>
    /// 學生類
    /// </summary>
    public class Student
    {
        /// <summary>
        /// 學號
        /// </summary>
        public string StuNo { get; set; }

        /// <summary>
        /// 姓名
        /// </summary>
        public string Name { get; set; }

        /// <summary>
        /// 年齡
        /// </summary>
        public int Age { get; set; }

        /// <summary>
        /// 性別
        /// </summary>
        public string Sex { get; set; }
    }
}

demo中的實體就這樣了

二、倉儲層

本demo的倉儲層需要引用我們的實體層TianYa.DotNetShare.Model

為什麼選擇用倉儲,原因很簡單,方便我們進行個性化擴展。在數據操作的底層進行其他個性化邏輯處理。

約定:

1、介面的定義放在根目錄下,介面的實現類,統一放到Impl文件夾,表示實現類目錄。

2、每個實體,對應一個倉儲的介面和實現類,即有多少個實體,就對應創建多少個介面和實現類。

我們新建一個Student的倉儲介面 IStudentRepository.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using TianYa.DotNetShare.Model;

namespace TianYa.DotNetShare.Repository
{
    /// <summary>
    /// 學生類倉儲層介面
    /// </summary>
    public interface IStudentRepository
    {
        /// <summary>
        /// 根據學號獲取學生信息
        /// </summary>
        /// <param name="stuNo">學號</param>
        /// <returns>學生信息</returns>
        Student GetStuInfo(string stuNo);
    }
}

接著在Impl中新建一個Student的倉儲實現StudentRepository.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using TianYa.DotNetShare.Model;

namespace TianYa.DotNetShare.Repository.Impl
{
    /// <summary>
    /// 學生類倉儲層
    /// </summary>
    public class StudentRepository : IStudentRepository, IDependency
    {
        /// <summary>
        /// 根據學號獲取學生信息
        /// </summary>
        /// <param name="stuNo">學號</param>
        /// <returns>學生信息</returns>
        public Student GetStuInfo(string stuNo)
        {
            //數據訪問邏輯,此處為了演示就簡單些
            var student = new Student();
            switch (stuNo)
            {
                case "10000":
                    student = new Student() { StuNo = "10000", Name = "張三", Sex = "", Age = 20 };
                    break;
                case "10001":
                    student = new Student() { StuNo = "10001", Name = "錢七七", Sex = "", Age = 18 };
                    break;
                case "10002":
                    student = new Student() { StuNo = "10002", Name = "李四", Sex = "", Age = 21 };
                    break;
                default:
                    student = new Student() { StuNo = "10003", Name = "王五", Sex = "", Age = 25 };
                    break;
            }

            return student;
        }
    }
}

該類同時實現了IStudentRepository介面和IDependency介面,其中實現IDependency介面的目的是為了後面的web端進行一次性註入

三、服務層

本demo的服務層需要引用我們的實體層TianYa.DotNetShare.Model和我們的倉儲層TianYa.DotNetShare.Repository

服務層與倉儲層類似,它屬於倉儲層的使用者。定義的方式也與倉儲層類似,有介面和Impl實現目錄。

但服務層不需要一個實體對應一個,服務層更多的是按照功能模塊進行劃分,比如一個登錄模塊,創建一個LoginService。

為了演示,我們新建一個Student的服務層介面IStudentService.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using TianYa.DotNetShare.Model;

namespace TianYa.DotNetShare.Service
{
    /// <summary>
    /// 學生類服務層介面
    /// </summary>
    public interface IStudentService
    {
        /// <summary>
        /// 根據學號獲取學生信息
        /// </summary>
        /// <param name="stuNo">學號</param>
        /// <returns>學生信息</returns>
        Student GetStuInfo(string stuNo);
    }
}

接著我們同樣在Impl中新建一個Student的服務層實現StudentService.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using TianYa.DotNetShare.Model;
using TianYa.DotNetShare.Repository;

namespace TianYa.DotNetShare.Service.Impl
{
    /// <summary>
    /// 學生類服務層
    /// </summary>
    public class StudentService : IStudentService, IDependency
    {
        /// <summary>
        /// 定義倉儲層學生抽象類對象
        /// </summary>
        protected IStudentRepository StuRepository;

        /// <summary>
        /// 空構造函數
        /// </summary>
        public StudentService() { }

        /// <summary>
        /// 構造函數
        /// </summary>
        /// <param name="stuRepository">倉儲層學生抽象類對象</param>
        public StudentService(IStudentRepository stuRepository)
        {
            this.StuRepository = stuRepository;
        }

        /// <summary>
        /// 根據學號獲取學生信息
        /// </summary>
        /// <param name="stuNo">學號</param>
        /// <returns>學生信息</returns>
        public Student GetStuInfo(string stuNo)
        {
            var stu = StuRepository.GetStuInfo(stuNo);
            return stu;
        }
    }
}

該類同時實現了IStudentService介面和IDependency介面,其中實現IDependency介面的目的是為了後面的web端進行一次性註入

四、Web層

本demo的web項目需要引用以下幾個程式集:

1、TianYa.DotNetShare.Model 我們的實體層

2、TianYa.DotNetShare.Service 我們的服務層

3、TianYa.DotNetShare.Repository 我們的倉儲層,正常我們的web項目是不應該使用倉儲層的,此處我們引用是為了演示IOC依賴註入

4、Autofac 依賴註入基礎組件

5、Autofac.Mvc5 依賴註入Mvc5的輔助組件

其中Autofac和Autofac.Mvc5可以從我們的NuGet上引用:

如果從線下已安裝的程式包源中找不到我們要的程式集,可以嘗試添加我們的程式包源,具體步驟如下:

名稱:nuget.org
源:https://api.nuget.org/v3/index.json

添加新的包源後點擊確定(如果已經有此包源就忽略該步驟),接下來就從NuGet上安裝我們需要的程式集。

依次點擊下載以下2個組件

至此我們所有的工作都已經準備好了,接下來就是重頭戲,開始做註入工作了。

 打開我們的Global.asax文件進行註入工作

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;

using Autofac;
using Autofac.Integration.Mvc;
using TianYa.DotNetShare.Model;
using TianYa.DotNetShare.Repository.Impl;
using TianYa.DotNetShare.Repository;

namespace TianYa.DotNetShare.MvcDemo
{
    public class MvcApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);

            AutofacRegister(); //Autofac依賴註入
        }

        /// <summary>
        /// Autofac依賴註入
        /// </summary>
        private void AutofacRegister()
        {
            var builder = new ContainerBuilder();
            //註冊MVC控制器(註冊所有到控制器,控制器註入,就是需要在控制器的構造函數中接收對象)
            builder.RegisterControllers(typeof(MvcApplication).Assembly);
            //構造函數註入,對StudentRepository與介面進行註入
            builder.RegisterType<StudentRepository>().As<IStudentRepository>();

            //設置依賴解析器
            var container = builder.Build();
            DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
        }
    }
}

至此,我們就完成了依賴註入工作,此方式為構造函數註入,接下來我們來看看控制器裡面怎麼弄。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

using TianYa.DotNetShare.Model;
using TianYa.DotNetShare.Service;
using TianYa.DotNetShare.Repository;

namespace TianYa.DotNetShare.MvcDemo.Controllers
{
    public class HomeController : Controller
    {
        /// <summary>
        /// 定義倉儲層學生抽象類對象
        /// </summary>
        protected IStudentRepository StuRepository;

        /// <summary>
        /// 通過構造函數進行註入
        /// 註意:參數是抽象類,而非實現類,因為已經在Global.asax中將實現類映射給了抽象類
        /// </summary>
        /// <param name="stuRepository">倉儲層學生抽象類對象</param>
        public HomeController(IStudentRepository stuRepository)
        {
            this.StuRepository = stuRepository;
        }

        public ActionResult Index()
        {
            var stu = StuRepository.GetStuInfo("10000");
            string msg = $"學號:10000,姓名:{stu.Name},性別:{stu.Sex},年齡:{stu.Age}。";
            return Content(msg);
        }

        public ActionResult About()
        {
            ViewBag.Message = "Your application description page.";

            return View();
        }

        public ActionResult Contact()
        {
            ViewBag.Message = "Your contact page.";

            return View();
        }
    }
}

至此,完成處理,接下來就是見證奇跡的時刻了,我們訪問 /home/index,看看是否能返回學生信息。

我們可以發現,返回了學生的信息,說明我們註入成功了。

總結:

1、採用的是構造函數註入的方式,在構造函數中初始化賦值。

2、StuRepository對象不需要實例化,即不需要new,降低了系統資源的消耗。

3、需要在Global.asax中對StudentRepository寫映射,如果倉儲類比較多的時候,就需要寫很多了,如何避免,這個在後面的篇幅中會講解到。

擴展: 上面講解了構造函數註入的方式,下麵擴展屬性註入的方式,在Global.asax中稍微修改下註入語句即可。

將:

builder.RegisterControllers(typeof(MvcApplication).Assembly);

改為:

builder.RegisterControllers(typeof(MvcApplication).Assembly).PropertiesAutowired();

PropertiesAutowired:表示允許屬性註入。

接下來我們來看下怎麼使用,修改我們的Global.asax代碼:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;

using Autofac;
using Autofac.Integration.Mvc;
using TianYa.DotNetShare.Model;
using TianYa.DotNetShare.Repository.Impl;
using TianYa.DotNetShare.Repository;
using TianYa.DotNetShare.Service;
using TianYa.DotNetShare.Service.Impl;

namespace TianYa.DotNetShare.MvcDemo
{
    public class MvcApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);

            AutofacRegister(); //Autofac依賴註入
        }

        /// <summary>
        /// Autofac依賴註入
        /// </summary>
        private void AutofacRegister()
        {
            var builder = new ContainerBuilder();
            //註冊MVC控制器(註冊所有到控制器,控制器註入,就是需要在控制器的構造函數中接收對象)
            builder.RegisterControllers(typeof(MvcApplication).Assembly).PropertiesAutowired();
            //構造函數註入,對StudentRepository與介面進行註入
            builder.RegisterType<StudentRepository>().As<IStudentRepository>();
            builder.RegisterType<StudentService>().As<IStudentService>();

            //設置依賴解析器
            var container = builder.Build();
            DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
        }
    }
}

修改我們的控制器代碼:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

using TianYa.DotNetShare.Model;
using TianYa.DotNetShare.Service;
using TianYa.DotNetShare.Repository;

namespace TianYa.DotNetShare.MvcDemo.Controllers
{
    public class HomeController : Controller
    {
        /// <summary>
        /// 定義倉儲層學生抽象類對象
        /// </summary>
        protected IStudentRepository StuRepository;

        /// <summary>
        /// 通過屬性註入,訪問修飾符必須為public,否則會註入失敗
        /// </summary>
        public IStudentService StuService { get; set; }

        /// <summary>
        /// 通過構造函數進行註入
        /// 註意:參數是抽象類,而非實現類,因為已經在Global.asax中將實現類映射給了抽象類
        /// </summary>
        /// <param name="stuRepository">倉儲層學生抽象類對象</param>
        public HomeController(IStudentRepository stuRepository)
        {
            this.StuRepository = stuRepository;
        }

        public ActionResult Index()
        {
            var stu = StuRepository.GetStuInfo("10000");
            var stu2 = StuService.GetStuInfo("10001");
            string msg = $"學號:10000,姓名:{stu.Name},性別:{stu.Sex},年齡:{stu.Age}<br />";
            msg += $"學號:10001,姓名:{stu2.Name},性別:{stu2.Sex},年齡:{stu2.Age}";
            return Content(msg);
        }

        public ActionResult About()
        {
            ViewBag.Message = "Your application description page.";

            return View();
        }

        public ActionResult Contact()
        {
            ViewBag.Message = "Your contact page.";

            return View();
        }
    }
}

再訪問一下我們的/home/index

我們可以發現,返回了學習信息,說明我們註入成功了。

另外通過這個例子我們可以發現在註入倉儲層對象StudentRepository時,不僅控制器中註入成功了,而且在服務層中也註入成功了,說明我們的Autofac的註入是全局的。

總結:

1、通過屬性註入,訪問修飾符必須為public,否則會註入失敗。

2、Autofac的註入是全局的。

 

未完待續......

 

參考博文:https://www.cnblogs.com/fei686868/p/10979790.html

版權聲明:如有雷同純屬巧合,如有侵權請及時聯繫本人修改,謝謝!!!


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1、java gc 2、java class的載入過程 3、java hashmap、 為什麼用紅黑樹、紅黑樹鄰接點為啥是8 。 4、拜占庭問題 5、一致性哈希 6、如何控制負載均衡。 7、http碼 302 403 。 8、https 加密過程。 9、操作系統虛存實現原理,交換,覆蓋區別。 10、 ...
  • 出自:http://1t.click/7TJ 目錄: 案例背景引入 特殊的電商大促場景 抗住大促的瞬時壓力需要幾台機器? 大促高峰期訂單系統的記憶體使用模型估算 記憶體到底該如何分配? 新生代垃圾回收優化之一:Survivor空間夠不夠 新生代對象躲過多少次垃圾回收後進入老年代? 多大的對象直接進入老年 ...
  • 類與類的關係 依賴關係 組合關係 組合: 將一個類的對象封裝成另一個類的對象的屬性. 繼承關係 繼承的優點: 1,增加了類的耦合性(耦合性不宜多,宜精)。 2,減少了重覆代碼。 3,使得代碼更加規範化,合理化 繼承:可以分 單繼承,多繼承 。 單繼承 第一種:直接執行 第二種:子類和父類都有相同功能 ...
  • 什麼是MVC MVC : 模型、視圖、控制器 , 是一種軟體設計規範,說明不是設計模式; 本質:將業務邏輯 , 數據 , 顯示 分離的方式來編寫代碼; 前後端分離; Model:數據模型,提供要展示的數據,一般我們都會把這兩個分離開來 , 數據Dao,服務層Service。 View :負責進行數據 ...
  • 第五節 一、字典 python的數據結構之一 字典 —— dict 定義:dic = {"key":"dajjlad"} 作用:存儲數據,大量,將數據和數據起到關聯作用 字典是可變的數據類型,無序的 所有的操作都通過鍵 # 鍵:必須是不可變的數據類型(可哈希),且唯一 不可哈希就是可變數據類型# 值 ...
  • 個人一直覺得對學習任何知識而言,概念是相當重要的。掌握了概念和原理,細節可以留給實踐去推敲。掌握的關鍵在於理解,通過具體的實例和實際操作來感性的體會概念和原理可以起到很好的效果。本文通過一些具體的例子簡單介紹一下python的多線程和多進程,後續會寫一些進程通信和線程通信的一些文章。 python多 ...
  • "鏈接" A 求出來到每座山的距離後,就可以計算出每隻貓等待的時間與出發時間的關係。 如果出發時間為$x$,求出來只貓的等待時間。這裡用$b_i$表示第i只貓的等待時間。然後我們將這些時間排序。問題就轉化為了,從m個有序的數中,選出p個,每個數字覆蓋以其為開頭的一段區間。這段區間的貢獻為$x\tim ...
  • 創建webapi項目 創建四個webapi項目,兩個處理業務,一個網關,一個驗證中心。四個項目對應的埠如下, ApiGateway:1999 IdentityServer:16690 Services.Api1:2108 Services.Api2:2343 添加Swagger支持 在兩個業務項目 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...