1. 程式人生 > >Asp.NET Core+ABP框架+IdentityServer4+MySQL+Ext JS之配置IdentityServer

Asp.NET Core+ABP框架+IdentityServer4+MySQL+Ext JS之配置IdentityServer

上一篇文章把專案建好了,現在要進行一些必要配置。由於IdentityServer4需要使用到3.2.5的包,而專案預設使用的是3.2.4的包,因而,我們需要先升級一下解決方案的包。在解決方案上單擊右鍵,在右鍵選單中選擇管理解決方案的NuGet包。在NuGet的標籤頁內,切換到更新標籤頁,會看到6個更新,選擇全部包,然後單擊更新按鈕。

包更新完以後,我們先做一次資料庫遷移。在EntityFrameworkCore專案中新增Pomelo.EntityFrameworkCore.MySql和Pomelo.EntityFrameworkCore.MySql.Design兩個包,以便支援MySql。為什麼不用Oracle提供的MySql.Data.EntityFrameworkCore呢?在微軟的文件《

MySQL EF Core Database Provider》中,該包只支援MySql,且還是預覽版狀態,而在Pomelo EF Core Database Provider for MySQL中,該包不單支援MySQL,還支援MariaDB,所以,怎麼選擇已經很明顯,可以說,筆者是毫不猶豫的選擇了Pomelo包。至於兩者的效能,筆者目前無法給出答案,只有等大神們的測試了。

至於測試資料庫,筆者選擇的是XAMMP帶的MySql,版本是10.1.13-MariaDB。資料庫所選的字符集為utf8_general_ci。雖然Pomelo建議選擇utf8mb4作為字符集(詳細資訊請參閱Pomelo《

Getting Started》),但建議不要選擇,因為“max key length is 767 bytes”這個錯誤會把你折磨死的。出現這個錯誤的原因是utf8以3位元組方式儲存一個字元的,而一列的索引長度最大值只能是767位元組,如果欄位的長度是256,那麼,索引的長度就是768了,正好超過1位元組,遷移就出問題了。如果使用utf8mb4,那麼,一個字元的長度就是4位元組,欄位的最大長度只能是191了,而這要修改的欄位就有很多了,所以在這練習了還是採用utf8算了。在實際專案中,建議使用utf8mb4,但要考慮帶索引的欄位的長度是191是否足夠。要想徹底解決這個問題,需要將欄位的索引擴大到3072欄位,但實現這個需要執行以下4個步驟:

  • SET GLOBAL innodb_file_format=Barracuda;
  • SET GLOBAL innodb_file_per_table=ON;
  • ROW_FORMAT=DYNAMIC; – or COMPRESSED (goes on end of CREATE)
  • innodb_large_prefix=1

以上4個步驟,1、2和4都可以在資料庫中直接修改。第3步則有點難度了,因為實現這個需要在建立表格時在CREATE語句中新增附加資訊,而這個在遷移程式碼中暫時沒找到解決方案,除非是使用Database First的方式來實現。

MySql的驅動準備好以後,需要修改資料庫連結,開啟Migrations專案和Web.Host專案中的appsettings.json檔案,將ConnectionStrings的Default值修改為“Server=localhost;database=simplecmswithabp;uid=root;pwd=abcd-1234;charset=UTF8;”。在生產環境中,不要使用root作為資料庫的連線使用者,這個大家應該都懂的。

修改資料庫連線後,還需要修改EntityFrameworkCore專案中的SimpleCmsWithAbpDbContextConfigurer.cs檔案,將方法中的UseSqlServer方法修改為UseMySql方法,完成後的程式碼如下:

    public static class SimpleCmsWithAbpDbContextConfigurer
    {
        public static void Configure(DbContextOptionsBuilder<SimpleCmsWithAbpDbContext> builder, string connectionString)
        {
            //builder.UseSqlServer(connectionString);
            builder.UseMySql(connectionString);           
        }

        public static void Configure(DbContextOptionsBuilder<SimpleCmsWithAbpDbContext> builder, DbConnection connection)
        {
            //builder.UseSqlServer(connection);
            builder.UseMySql(connection);
        }
    }

下一步要修改欄位長度為256,且需要建立索引的欄位的長度。開啟20170424115119_Initial_Migrations.cs檔案,然後使用搜索功能尋找256,經過一輪搜尋和索引欄位對比後,最終需要修改的欄位包括:

  • AbpLanguageTexts表:Key
  • AbpUsers表:EmailAddress和NormalizedEmailAddress
  • AbpUserLogins表:ProviderKey
  • AbpSettings表:Name

長度修改為255就行了。如果使用utf8mb4,需要修改為191。欄位修改完成後,將Migrator專案設定為啟動專案,然後執行,會看到如下圖所示的結果:

遷移資料庫

在視窗中輸入y,等待以後後出現以下資訊,說明遷移已經完成了,按回車退出程式。

2017-12-16 09:54:29 | HOST database migration started...
2017-12-16 09:54:34 | HOST database migration completed.
2017-12-16 09:54:34 | --------------------------------------------------------
2017-12-16 09:54:34 | All databases have been migrated.
Press ENTER to exit...

使用資料庫工具開啟資料庫,會看到下圖所示的表格:

資料庫

首先要做的是在EntityFrameworkCore專案中新增 Abp.ZeroCore.IdentityServer4和 Abp.ZeroCore.IdentityServer4.EntityFrameworkCore的引用。然後開啟SimpleCmsWithAbpEntityFrameworkModule.cs檔案,在類定義上新增依賴項,具體程式碼如下:

    [DependsOn(
        typeof(SimpleCmsWithAbpCoreModule), 
        typeof(AbpZeroCoreEntityFrameworkCoreModule),
        typeof(AbpZeroCoreIdentityServerEntityFrameworkCoreModule))]
    public class SimpleCmsWithAbpEntityFrameworkModule : AbpModule
    ……

下面要配置Startup Class,開啟SimpleCmsWithAbp.Web.Host專案下Startup檔案的Startup.cs檔案,在IdentityRegistrar.Register(services)這句下新增以下程式碼:

            services.AddIdentityServer()
                .AddDeveloperSigningCredential()
                .AddInMemoryIdentityResources(IdentityServerConfig.GetIdentityResources())
                .AddInMemoryApiResources(IdentityServerConfig.GetApiResources())
                .AddInMemoryClients(IdentityServerConfig.GetClients())
                .AddAbpPersistedGrants<IAbpPersistedGrantDbContext>()
                .AddAbpIdentityServer<User>();

在Configure方法內,註釋掉app.UseAuthentication這句,因為UseIdentityServer方法會自動呼叫UseAuthentication方法。在app.UseJwtTokenMiddleware下

app.UseIdentityServer();

為什麼不像文章中那樣在呼叫UseJwtTokenMiddleware方法時將IdentityBearer作為引數呢?主要原因是這個引數是在授權客戶端與應用程式是同一應用程式才使用,而我們預想的情況是在不同應用程式,因而不用採用這個引數。

如果打算使用記憶體來提供資源,可以參考文章在SimpleCmsWithAbp.Web.Host專案中新增一個名為IdentityServerConfig的靜態類,用來指定資源,程式碼請參考《Identity Server Integration》一文。如果打算使用資料庫來管理資源,可以忽略這一步。

下面要做的是SimpleCmsWithAbpDbContext新增IAbpPersistedGrantDbContext介面。切換到EntityFrameworkCore專案,開啟SimpleCmsWithAbpDbContext.cs檔案,在類定義的後面新增IAbpPersistedGrantDbContext介面,以實現授權操作:

public class SimpleCmsWithAbpDbContext : AbpZeroDbContext<Tenant, Role, User, SimpleCmsWithAbpDbContext>, IAbpPersistedGrantDbContext

新增IAbpPersistedGrantDbContext介面後,需要在類內實現介面功能,程式碼如下:

    public DbSet<PersistedGrantEntity> PersistedGrants { get; set; }
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);

        modelBuilder.ConfigurePersistedGrantEntity();
    }

好了,IdentityServer的配置基本完成了,但在《Identity Server Integration》一文中,資源的定義使用的是記憶體定義模式(AddInMemoryIdentityResources),對於專案來說,這不便於資源的管理,因而,一般會通過資料庫來實現管理,而要實現這個,就要參考Using EntityFramework Core for configuration and operational data一文來實現。

本來打算從IConfigurationDbContext介面派生,將ConfigurationDbContext合併到SimpleCmsWithAbpDbContext,但水平有限,嘗試了不少方法都不行,只能按照文章的步驟的去實現了。先在EntityFrameworkCore專案新增IdentityServer4.EntityFramework包,再將以上呼叫AddIdentityServer方法的程式碼替換為以下程式碼:

            var connectionString = _appConfiguration.GetConnectionString("Default");
            services.AddIdentityServer()
                .AddDeveloperSigningCredential()
                .AddConfigurationStore(options =>
                {
                    options.ConfigureDbContext = builder =>
                        builder.UseMySql(connectionString, sql => sql.MigrationsAssembly("SimpleCmsWithAbp.EntityFrameworkCore"));
                })
                //.AddInMemoryIdentityResources(IdentityServerConfig.GetIdentityResources())
                //.AddInMemoryApiResources(IdentityServerConfig.GetApiResources())
                //.AddInMemoryClients(IdentityServerConfig.GetClients())
                .AddAbpPersistedGrants<IAbpPersistedGrantDbContext>()
                .AddAbpIdentityServer<User>(); 

程式碼添加了AddConfigurationStore方法來配置ConfigurationDbContext,並註釋掉了使用記憶體資源的程式碼。在ConfigurationDbContext方法內,指定了ConfigurationDbContext將使用MySql資料庫,而它的遷移模組在EntityFrameworkCore專案內。

接下來要新增遷移,我們不需要採用文章所介紹的方法。先將Web.Host專案設定為啟動專案,不然會出現“No DbContext named ‘ConfigurationDbContext’ was found”的錯誤,,原先是遷移需要根據上下文來尋找Context。在IDE中,切換到程式包管理器控制器,將預設專案設定為SimpleCmsWithAbp.Web.Host,然後輸入以下命名:

Add-Migration -Name InitialIdentityServerConfigurationDbMigration -Context ConfigurationDbContext  -OutputDir Migrations/IdentityServer/ConfigurationDb -Project SimpleCmsWithAbp.EntityFrameworkCore

命令將使用ConfigurationDbContext建立一個名為InitialIdentityServerConfigurationDbMigration 的遷移。遷移檔案將輸出到SimpleCmsWithAbp.EntityFrameworkCore專案的Migrations/IdentityServer/ConfigurationDb資料夾。

命令執行後,會在EntityFrameworkCore專案的Migrations資料夾內看到下圖所示資料夾和檔案:

遷移檔案

餘下的工作是初始化資料庫,這裡也不採用文章所使用的方法,將參考EntityFrameworkCore專案中的遷移方式來實現。先要做的是在EntityFrameworkCore\Seed資料夾下建立IdentityServer資料夾,並新增以下4個類檔案:

  • DefaultApiResourceCreator.cs
    public class DefaultApiResourceCreator
    {
        private readonly ConfigurationDbContext _context;

        public DefaultApiResourceCreator(ConfigurationDbContext context)
        {
            _context = context;
        }

        public void Create()
        {
            CreateDefaultApiResource();
        }

        private void CreateDefaultApiResource()
        {
            if (_context.ApiResources.Any()) return;
            var defaultApiResource = new ApiResource() { Name = "default-api", DisplayName = "Default (all) API" };
            _context.ApiResources.Add(defaultApiResource);
            _context.SaveChanges();
        }
    }
  • DefaultClientCreator.cs
    public class DefaultClentCreator
    {
        private readonly ConfigurationDbContext _context;

        public DefaultClentCreator(ConfigurationDbContext context)
        {
            _context = context;
        }

        public void Create()
        {
            CreateDefaultClient();
        }

        private void CreateDefaultClient()
        {
            if (_context.Clients.Any()) return;
            foreach (var client in GetClients())
            {
                _context.Clients.Add(client.ToEntity());
            }
            _context.SaveChanges();
        }

        private static IEnumerable<IdentityServer4.Models.Client> GetClients() => new List<IdentityServer4.Models.Client>
            {
                new IdentityServer4.Models.Client
                {
                    ClientId = "client",
                    AllowedGrantTypes =
                    {
                        GrantType.ResourceOwnerPassword,
                        GrantType.ClientCredentials
                    },
                    AllowedScopes = {"default-api"},
                    ClientSecrets =
                    {
                        new IdentityServer4.Models.Secret("secret".Sha256())
                    }
                }
            };
    }
  • DefaultIdentityResourceCreator.cs
    public class DefaultIdentityResourceCreator
    {
        private readonly ConfigurationDbContext _context;

        public DefaultIdentityResourceCreator(ConfigurationDbContext context)
        {
            _context = context;
        }

        public void Create()
        {
            CreateDefaultIdentityResource();
        }

        private void CreateDefaultIdentityResource()
        {
            if (_context.IdentityResources.Any()) return;
            foreach (var resource in GetIdentityResource())
            {
                _context.IdentityResources.Add(resource.ToEntity());
            }
            _context.SaveChanges();
        }

        private static IEnumerable<IdentityServer4.Models.IdentityResource> GetIdentityResource()
        {
            return new List<IdentityServer4.Models.IdentityResource>
            {
                new IdentityResources.OpenId(),
                new IdentityResources.Profile(),
                new IdentityResources.Email(),
                new IdentityResources.Phone()
            };

        }
    }
  • InitialIConfigurationDbBuilder.cs
    public class InitialIConfigurationDbBuilder
    {
        private readonly ConfigurationDbContext _context;

        public InitialIConfigurationDbBuilder(ConfigurationDbContext context)
        {
            _context = context;
        }

        public void Create()
        {
            new DefaultApiResourceCreator(_context).Create();
            new DefaultIdentityResourceCreator(_context).Create();
            new DefaultClentCreator(_context).Create();

            _context.SaveChanges();
        }
    }

這4個類新增完成後,在SeedHelper類內新增以下兩個方法用來初始化資源:

        public static void SeedIdentityServerDb(IIocResolver iocResolver)
        {
            WithDbContext<ConfigurationDbContext>(iocResolver, SeedIdentityServerDb);
        }

        public static void SeedIdentityServerDb(ConfigurationDbContext context)
        {
            new InitialIConfigurationDbBuilder(context).Create();
        }

在EntityFrameworkCore專案的EntityFrameworkCore資料夾內,參考AbpZeroDbMigrator建立一個AbpZeroIdentityServerDbMigrator類用來遷移配置庫,具體程式碼如下:

    public class AbpZeroIdentityServerDbMigrator : AbpZeroDbMigrator<ConfigurationDbContext>
    {
        public AbpZeroIdentityServerDbMigrator(
            IUnitOfWorkManager unitOfWorkManager,
            IDbPerTenantConnectionStringResolver connectionStringResolver,
            IDbContextResolver dbContextResolver)
            : base(
                unitOfWorkManager,
                connectionStringResolver,
                dbContextResolver)
        {
        }
    }

AbpZeroIdentityServerDbMigrator與AbpZeroDbMigrator主要的不同在派生於AbpZeroDbMigrator時,實體類是ConfigurationDbContext而不是SimpleCmsWithAbpDbContext。

試了一下看能不能在Migrator專案內遷移資料庫,但老是出現“No component for supporting the service IdentityServer4.EntityFramework.DbContexts.ConfigurationDbContext was found”的錯誤,放棄了,還是在Start類內初始化吧。在Configure方法內,app.UseAbp程式碼下,新增以下遷移程式碼:

            using (var serviceScope = app.ApplicationServices.GetService<IServiceScopeFactory>().CreateScope())
            {
                var migrator = serviceScope.ServiceProvider.GetRequiredService<AbpZeroIdentityServerDbMigrator>();
                migrator.CreateOrMigrateForHost(SeedHelper.SeedIdentityServerDb);

            }

IdentiyServer現在基本上是配置好了,但要使應用程式跑起來,還得修改個地方,切換到Web.Core專案,開啟Controllers資料夾下的TokenAuthController.cs檔案,找到215行以下這句:

var nameIdClaim = claims.First(c => c.Type == ClaimTypes.NameIdentifier);

將它修改為:

var nameIdClaim = claims.First(c => c.Type == AbpClaimTypes.UserId);

使用ClaimTypes.NameIdentifier作為比較,nameIdClaim 永遠返回空的列表,導致不能生成token,這應該是ABP的bug。修改後就可以使用postman來測試了。

開啟postman,在位址列輸入地址:http://localhost:21021/api/TokenAuth/Authenticate。提交方式選擇POST。在Headers中輸入以下兩個引數:
- Content-Type:application/json
- Abp.TenantId:1

在body中輸入以下資料:

{
  "userNameOrEmailAddress": "[email protected]",
  "password": "123qwe",
  "rememberClient": false
}

單擊Send按鈕後,會看到如下圖所示輸出:

登入

將圖中的accessToken複製出來。新建一個頁面標籤,提交方式設定為GET,地址輸入:http://localhost:21021/api/services/app/User/GetAll?SkipCount=0&MaxResultCount=100。在Headers中,在Key中輸入Authorization,在value中,先輸入Bearer加一個空格,然後在空格後把剛才複製的accessToken貼上在後面。再加上Abp.TenantId後,單擊Send,將看到如下圖所示的結果:

從圖中可以看到,通過accessToken可以順利獲取資料了,這說明IdentityServer執行正常。

獲取使用者列表

今天就說到這裡了。

相關推薦

Asp.NET Core+ABP框架+IdentityServer4+MySQL+Ext JS配置IdentityServer

上一篇文章把專案建好了,現在要進行一些必要配置。由於IdentityServer4需要使用到3.2.5的包,而專案預設使用的是3.2.4的包,因而,我們需要先升級一下解決方案的包。在解決方案上單擊右鍵,在右鍵選單中選擇管理解決方案的NuGet包。在NuGet

Asp.NET Core+ABP框架+IdentityServer4+MySQL+Ext JS驗證碼

驗證碼這東西,有人喜歡有人不喜歡。對於WebApi是否需要驗證碼,沒去研究過,只是原來的SimpleCMS有,就加上吧。 在WeiApi上使用驗證碼,關鍵的地方在於WeiApi是沒有狀態的,也就是說,不能使用Session來儲存驗證碼。因而,在WebApi

Asp.NET Core+ABP框架+IdentityServer4+MySQL+Ext JS文章管理

登入完成後,我們繼續來完成餘下的功能。本文要完成的是文章管理功能,主要包括後臺應用層服務以及客戶端儲存(Store)的資料訪問調整。 由於本文涉及的類很多,因而,只挑了一些比較有代表性的類來講解,其餘的,有興趣可以自行下載程式碼來研究,或者發私信、評論

ASP.NET Core 執行原理解剖[2]-Hosting補充配置介紹

在上一章中,我們介紹了 ASP.NET Core 的啟動過程,主要是對 WebHost 原始碼的探索。而本文則是對上文的一個補充,更加偏向於實戰,詳細的介紹一下我們在實際開發中需要對 Hosting 做一些配置時經常用到的幾種方式。 目錄 本系列文章將會從原始碼分析來講解

ASP.net Core 2.0 EF (mysql) 遷移 正確姿勢

com update reat .com ttr 數據庫 pda creat mic 用於進行遷移的 Entity Framework Core NuGet 包 註意:必須通過編輯 .csproj 文件來安裝此包;不能使用 install-package 命令或程序包管理器

使用 ASP.NET Core Identity 的 IdentityServer4 授權服務器(二)

length 字段 dbm dconf logs 字段長度 database asp using 在 使用 ASP.NET Core Identity 的 IdentityServer4 授權服務器(1) 中,IdentityServer4 使用的是內存數據,不方便靈活,這

asp.net core 2.1 DBfirst MySQL 執行命令出錯

Scaffold-DbContext "Data Source=localhost;Initial Catalog=FriendSourceDB;User ID=root;Password=;" Pomelo.EntityFrameworkCore.MySql -OutputDir EFModel

ASP.NET Core 入門教程 2、使用ASP.NET Core MVC框架構建Web應用

一、前言 1、本文主要內容 使用dotnet cli建立基於解決方案(sln+csproj)的專案 使用Visual Studio Code開發基於解決方案(sln+csproj)的專案 Visual Studio Code Solution外掛( vscode-solution-explorer)基礎使用

ASP.NET CORE API Swagger+IdentityServer4授權驗證

簡介 本來不想寫這篇博文,但在網上找到的文章部落格都沒有完整配置資訊,所以這裡記錄下。 不瞭解IdentityServer4的可以看看我之前寫的入門博文 Swagger 官方演示地址 原始碼地址 配置IdentityServer4服務端 首先建立一個新的ASP.NET Core專案。 &nb

[ASP.NET Core 3框架揭祕] 跨平臺開發體驗: Windows [上篇]

微軟在千禧年推出 .NET戰略,並在兩年後推出第一個版本的.NET Framework和IDE(Visual Studio.NET 2002,後來改名為Visual Studio),如果你是一個資深的.NET程式設計師,相信傳統的.NET應用的開發方式已經深深地烙印在你的腦子裡面。.NET Core帶來了全新

[ASP.NET Core 3框架揭祕] 跨平臺開發體驗: Windows [中篇]

我們在《上篇》利用dotnet new命令建立了一個簡單的控制檯程式,接下來我們將它改造成一個ASP.NET Core應用。一個ASP.NET Core應用構建在ASP.NET Core框架之上,ASP.NET Core框架利用一個訊息處理管道完成對HTTP請求的監聽、接收、處理和最終的響應。ASP.NET

[ASP.NET Core 3框架揭祕] 跨平臺開發體驗: Windows [下篇]

由於ASP.NET Core框架在本質上就是由伺服器和中介軟體構建的訊息處理管道,所以在它上面構建的應用開發框架都是建立在某種型別的中介軟體上,整個ASP.NET Core MVC開發框架就是建立在用來實現路由的EndpointRoutingMiddleware和EndpointMiddleware中介軟體上

[ASP.NET Core 3框架揭祕] 跨平臺開發體驗: Mac OS

除了微軟自家的Windows平臺, .NET Core針對Mac OS以及各種Linux Distribution(RHEL、Ubuntu、Debian、Fedora、CentOS和SUSE等)都提供了很好的支援。我們先來體驗一下使用Mac來開發.NET Core應用,在這之前我們照例先得在Mac OS上構建

[ASP.NET Core 3框架揭祕] 跨平臺開發體驗: Linux

如果想體驗Linux環境下開發.NET Core應用,我們有多種選擇。一種就是在一臺物理機上安裝原生的Linux,我們可以根據自身的喜好選擇某種Linux Distribution,目前來說像RHEL、Ubuntu、Debian、Fedora、CentOS和SUSE這些主流的Distribution都是支援的

[ASP.NET Core 3框架揭祕] 跨平臺開發體驗: Docker

對於一個 .NET Core開發人員,你可能沒有使用過Docker,但是你不可能沒有聽說過Docker。Docker是Github上最受歡迎的開源專案之一,它號稱要成為所有云應用的基石,並把網際網路升級到下一代。Docker是dotCloud公司開源的一款產品,從其誕生那一刻算起,在短短兩三年時間裡就成為了開

[ASP.NET Core 3框架揭祕] 依賴注入:控制反轉

ASP.NET Core框架建立在一些核心的基礎框架之上,這些基礎框架包括依賴注入、檔案系統、配置選項和診斷日誌等。這些框架不僅僅是支撐ASP.NET Core框架的基礎,我們在進行應用開發的時候同樣會頻繁地使用到它們。對於這裡提到的這幾個基礎框架,依賴注入尤為重要。ASP.NET Core應用在啟動以及後續

[ASP.NET Core 3框架揭祕] 依賴注入:IoC模式

正如我們在《依賴注入:控制反轉》提到過的,很多人將IoC理解為一種“面向物件的設計模式”,實際上IoC不僅與面向物件沒有必然的聯絡,它自身甚至算不上是一種設計模式。一般來講,設計模式提供了一種解決某種具體問題的方案,但是IoC既沒有一個針對性的問題領域,其自身也沒有提供一種可操作性的解

[ASP.NET Core 3框架揭祕] 依賴注入:依賴注入模式

IoC主要體現了這樣一種設計思想:通過將一組通用流程的控制權從應用轉移到框架之中以實現對流程的複用,並按照“好萊塢法則”實現應用程式的程式碼與框架之間的互動。我們可以採用若干設計模式以不同的方式實現IoC,比如我們在前面介紹的模板方法、工廠方法和抽象工廠,接下來我們介紹一種更有價值的I

[ASP.NET Core 3框架揭祕] 依賴注入:一個Mini版的依賴注入框架

在前面的章節中,我們從純理論的角度對依賴注入進行了深入論述,我們接下來會對.NET Core依賴注入框架進行單獨介紹。為了讓讀者朋友能夠更好地理解.NET Core依賴注入框架的設計與實現,我們按照類似的原理建立了一個簡易版本的依賴注入框架,也就是我們在前面多次提及的Cat。原始碼下載普通服務的註冊與消費泛型

[ASP.NET Core 3框架揭祕] 依賴注入[5]: 利用容器提供服務

毫不誇張地說,整個ASP.NET Core框架是建立在依賴注入框架之上的。ASP.NET Core應用在啟動時構建管道以及利用該管道處理每個請求過程中使用到的服務物件均來源於依賴注入容器。該依賴注入容器不僅為ASP.NET Core框架自身提供必要的服務,同時也是應用程式的服務提供者,依賴注入已經成為了ASP