添加EF上下文對象,添加接口、實現類以及無處不在的依賴注入(DI)
目錄索引
簡介
上一章,我們介紹了安裝和新建控制器、視圖,這一章我們來創建個數據模型,並且添加接口和實現類。
添加EF上下文對象
按照我們以前的習慣,我們還是新建幾個文件夾
Commons:存放幫助類
Domians:數據模型
Services:接口和實現類

我們在Domains文件夾下添加一個類庫 Domain

我們新建一個類 ApplicationDbContext 繼承 DbContext
1 using Microsoft.EntityFrameworkCore;
2
3 namespace Domain
4 {
5 public class ApplicationDbContext : DbContext
6 {
7 public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
8 : base(options)
9 {
10 }
11
12 protected override void OnModelCreating(ModelBuilder builder)
13 {
14 base.OnModelCreating(builder);
15 }
16 }
17 }
說明:
DbContext 需要引用 Microsoft.EntityFrameworkCore
第一種方式:選中 DbContext 通過組合鍵 Ctrl+. 添加 Microsoft.EntityFrameworkCore 引用
第二種方式:在Domain 類庫的 project.json 中添加 Microsoft.EntityFrameworkCore 引用
然后,我們打開 \src\Startu.cs 修改 ConfigureServices(IServiceCollection services) 方法,增加對EF的支持(黃色高亮):
1 // This method gets called by the runtime. Use this method to add services to the container.
2 public void ConfigureServices(IServiceCollection services)
3 {
4 // Add framework services.
5 services.AddApplicationInsightsTelemetry(Configuration);
6
7 services.AddDbContext<ApplicationDbContext>(options =>options.UseSqlServer(Configuration.GetConnectionString("SqlServerConnection")));
8
9 services.AddMvc();
10
11 }
上面的 SqlServerConnection 是我們的數據庫連接字符串,它的配置在 \src\appsettings.json 文件中(這個名字讓我們想起了appsetting.config):

這樣,實際上我們就完成了,但是我們后面會用到,我們目前不操作數據。
添加接口和實現類
我們來添加一個接口和實現類,來看一下Asp.net Core的依賴注入。
我們在Services文件夾下添加一個類庫 Service

我們在 Service 類庫下,新建 三個文件夾:
IDao:存放基礎操作類
IService:存放接口文件
ServiceImp:存放實現類
IDao 我們先不管,我們后面 IRepositorycs和Repositorycs(DDD 領域驅動設計) 會使用到,我們主要是添加一個接口和實現類。為了更好的歸類接口和實現類,我們在 IService 和 ServiceImp 文件夾下面分別建立一個文件夾 SysManage 用於存放系統管理接口。
我們在 \IService\SysManage\ 下新建一個接口 IUserManage
1 namespace Service.IService
2 {
3 public interface IUserManage
4 {
5 /// <summary>
6 /// 測試接口
7 /// </summary>
8 /// <returns></returns>
9 string Test();
10 }
11 }
我們在 \ServiceImp\SysManage\ 下新建一個實現類 UserManage
1 namespace Service.ServiceImp
2 {
3 public class UserManage : IService.IUserManage
4 {
5 public string Test()
6 {
7 return "我實現了接口方法Test";
8 }
9 }
10 }
修改 \src\Startu.cs 的 ConfigureServices(IServiceCollection services) 方法,實現注入(黃色高亮):
1 // This method gets called by the runtime. Use this method to add services to the container.
2 public void ConfigureServices(IServiceCollection services)
3 {
4 // Add framework services.
5 services.AddApplicationInsightsTelemetry(Configuration);
6
7 services.AddDbContext<ApplicationDbContext>(options =>options.UseSqlServer(Configuration.GetConnectionString("SqlServerConnection")));
8
9 services.AddMvc();
10
11 // Add application services.
12 services.AddTransient<Service.IService.IUserManage, Service.ServiceImp.UserManage>();
13 }
說明:

調用接口
注入有三種方式:構造器注入、屬性注入 和 方法注入。我們在 【無私分享:從入門到精通ASP.NET MVC】 系列中大部分使用的是 屬性注入,今天我們使用的是 構造器注入:
我們在 HomeController 中 聲明接口
private readonly IUserManage _UserManage;
在控制器構造函數中 添加:
public HomeController(IUserManage UserManage)
{
_UserManage = UserManage;
}
依賴注入框架會自動找到 IUserManage 實現類的實例,賦值給該構造函數
我們在 About 視圖中 測試一下:
public IActionResult About()
{
ViewData["Message"] = _UserManage.Test();
return View();
}
Ctrl+F5 運行一下:

說明注入成功!(在Asp.net Core中,我們修改代碼后直接保存刷新頁面就可以,不再像以前那樣 要重新編譯生成,這點還是很贊的。)
三種注入方式:
構造器注入
構造器注入就在在構造函數中借助參數將依賴的對象注入到創建的對象之中。如下面的代碼片段所示,Foo針對Bar的依賴體現在只讀屬性Bar上,針對該屬性的初始化實現在構造函數中,具體的屬性值由構造函數的傳入的參數提供。當DI容器通過調用構造函數創建一個Foo對象之前,需要根據當前注冊的類型匹配關系以及其他相關的注入信息創建並初始化參數對象。
1: public class Foo
2: {
3: public IBar Bar{get; private set;}
4: public Foo(IBar bar)
5: {
6: this.Bar = bar;
7: }
8: }
除此之外,構造器注入還體現在對構造函數的選擇上面。如下面的代碼片段所示,Foo類上面定義了兩個構造函數,DI容器在創建Foo對象之前首選需要選擇一個適合的構造函數。至於目標構造函數如何選擇,不同的DI容器可能有不同的策略,比如可以選擇參數做多或者最少的,或者可以按照如下所示的方式在目標構造函數上標注一個相關的特性(我們在第一個構造函數上標注了一個InjectionAttribute特性)。
1: public class Foo
2: {
3: public IBar Bar{get; private set;}
4: public IBaz Baz {get; private set;}
5:
6: [Injection]
7: public Foo(IBar bar)
8: {
9: this.Bar = bar;
10: }
11:
12: public Foo(IBar bar, IBaz):this(bar)
13: {
14: this.Baz = baz;
15: }
16: }
屬性注入
如果依賴直接體現為類的某個屬性,並且該屬性不是只讀的,我們可以讓DI容器在對象創建之后自動對其進行賦值進而達到依賴自動注入的目的。一般來說,我們在定義這種類型的時候,需要顯式將這樣的屬性標識為需要自動注入的依賴屬性,以區別於該類型的其他普通的屬性。如下面的代碼片段所示,Foo類中定義了兩個可讀寫的公共屬性Bar和Baz,我們通過標注InjectionAttribute特性的方式將屬性Baz設置為自動注入的依賴屬性。對於由DI容器提供的Foo對象,它的Baz屬性將會自動被初始化。
1: public class Foo
2: {
3: public IBar Bar{get; set;}
4:
5: [Injection]
6: public IBaz Baz {get; set;}
7: }
方法注入
體現依賴關系的字段或者屬性可以通過方法的形式初始化。如下面的代碼片段所示,Foo針對Bar的依賴體現在只讀屬性上,針對該屬性的初始化實現在Initialize方法中,具體的屬性值由構造函數的傳入的參數提供。我們同樣通過標注特性(InjectionAttribute)的方式將該方法標識為注入方法。DI容器在調用構造函數創建一個Foo對象之后,它會自動調用這個Initialize方法對只讀屬性Bar進行賦值。在調用該方法之前,DI容器會根據預先注冊的類型映射和其他相關的注入信息初始化該方法的參數。
1: public class Foo
2: {
3: public IBar Bar{get; private set;}
4:
5: [Injection]
6: public Initialize(IBar bar)
7: {
8: this.Bar = bar;
9: }
10: }
希望跟大家一起學習Asp.net Core
剛開始接觸,水平有限,很多東西都是自己的理解和翻閱網上大神的資料,如果有不對的地方和不理解的地方,希望大家指正!
雖然Asp.net Core 現在很火熱,但是網上的很多資料都是前篇一律的復制,所以有很多問題我也暫時沒有解決,希望大家能共同幫助一下!
原創文章 轉載請尊重勞動成果 http://yuangang.cnblogs.com

