1. 程式人生 > >ASP.Net Core 3.1 With Autofac ConfigureServices returning an System.IServiceProvider isn't supported.

ASP.Net Core 3.1 With Autofac ConfigureServices returning an System.IServiceProvider isn't supported.

ASP.Net Core 3.1 With Autofac ConfigureServices returning an System.IServiceProvider isn't supported. # 前言 Autofac在ASP.Net Core3.0以後,整合方式有所調整。在ASP.Net Core2中我們一般是把`Startup`的`ConfigureServices`方法返回值型別改為`IServiceProvider`。我們可以先看一下部分程式碼: ``` c# public IServiceProvider ConfigureServices(IServiceCollection services) { services.AddMvc(); //xxxxxx你的其他程式碼 省略........... //用Autofac來替換IOC容器 返回值由 void 修改為 IServiceProvider var containerBuilder = new ContainerBuilder(); containerBuilder.RegisterModule(); containerBuilder.Populate(services); var container = containerBuilder.Build(); //將當前的容器儲存起來,用於後續使用 AutofacHelper.Container = container; return new AutofacServiceProvider(container); } ``` > 完整程式碼可以參考我之前的開源專案:[LJD.APP](https://github.com/jellydong/LJDAPP "LJD.APP"):https://github.com/jellydong/LJDAPP > > CustomAutofacModule是把Autofac的配置單獨寫,不然都放在Startup中有點臃腫。 我們把這段程式碼Copy到ASP.Net Core3.1的專案中啟動: > 異常:`System.NotSupportedException:“ConfigureServices returning an System.IServiceProvider isn't supported.”` 就是說,我們不能再這樣修改返回值型別, > 官網解釋:您不能再`IServiceProvider`從中返回`ConfigureServices`,也不能將服務提供者工廠新增到服務集合中。 那我們按照官方文件的方法修改一下。 # 建立ASP.Net Core3.1 Web專案 效果圖 ![](https://img2020.cnblogs.com/blog/1006210/202007/1006210-20200717172442442-918240798.png) ## Services 建立完成後我們先建立資料夾`Services`,用來測試使用。 在`Services`資料夾下建立`Iservice` ``` c# namespace DotNetCore3AutoFac.Services { public interface IService { string SayHi(); } } ``` 然後建立兩個`Iservice`的實現類`OneService`、`TwoService` ``` c# namespace DotNetCore3AutoFac.Services { public class OneService:IService { public string SayHi() { return "One Say Hi"; } } } ``` ``` c# namespace DotNetCore3AutoFac.Services { public class TwoService:IService { public string SayHi() { return "Two Say Hi"; } } } ``` ## Autofac 建立`Autofac`資料夾,在該資料夾下建立`CustomAutofacModule` ``` c# using Autofac; using DotNetCore3AutoFac.Services; namespace DotNetCore3AutoFac.Autofac { public class CustomAutofacModule : Module { /// /// AutoFac註冊類 ///
/// protected override void Load(ContainerBuilder builder) { builder.RegisterType().As(); } } } ``` 我們先用`OneService`去實現,當然,正常這裡會有很多很多的程式碼~ ## 修改`Startup`和`Program` > 當然,需要安裝Autofac的包:`Autofac`&`Autofac.Extensions.DependencyInjection` 前序工作都完成了,我們來改最重要的,首先修改我們的`Program`,增加`UseServiceProviderFactory(new AutofacServiceProviderFactory())` ``` c# namespace DotNetCore3AutoFac { public class Program { public static void Main(string[] args) { CreateHostBuilder(args).Build().Run(); } public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) //改用Autofac來實現依賴注入 .UseServiceProviderFactory(new AutofacServiceProviderFactory()) .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup(); }); } } ``` 然後我們修改`Startup` > 1、增加屬性`AutofacContainer` > > 2、增加方法`ConfigureContainer`它在`ConfigureServices`之後執行 > > 3、給屬性賦值(可選) ``` c# using Autofac; using Autofac.Extensions.DependencyInjection; using DotNetCore3AutoFac.Autofac; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; namespace DotNetCore3AutoFac { public class Startup { public Startup(IConfiguration configuration) { Configuration = configuration; } public IConfiguration Configuration { get; } //autofac 新增 public ILifetimeScope AutofacContainer { get; private set; } // This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { services.AddControllersWithViews(); } //autofac 新增 public void ConfigureContainer(ContainerBuilder builder) { // 直接用Autofac註冊我們自定義的 builder.RegisterModule(new CustomAutofacModule()); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { app.UseExceptionHandler("/Home/Error"); // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. app.UseHsts(); } //autofac 新增 可選 this.AutofacContainer = app.ApplicationServices.GetAutofacRoot(); app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseRouting(); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapControllerRoute( name: "default", pattern: "{controller=Home}/{action=Index}/{id?}"); }); } } } ``` ## 驗證 我們修改下`HomeController` ![](https://img2020.cnblogs.com/blog/1006210/202007/1006210-20200717172505241-929227965.png) 執行,斷點看下結果是否正確 ![](https://img2020.cnblogs.com/blog/1006210/202007/1006210-20200717172522563-1900124815.png) 修改下實現類,也是正確的~ ![](https://img2020.cnblogs.com/blog/1006210/202007/1006210-20200717172532680-727961364.png) # 總結 其實很多官方文件都講述了,因為自己近期打算把原來的專案[LJD.APP](https://github.com/jellydong/LJDAPP "LJD.APP"):https://github.com/jellydong/LJDAPP升級到.Net Core 3.1上,當然是一個簡化版本https://github.com/jellydong/Jelly.Simple。 所以不要怕英文,翻譯外掛那麼好用,基本都能看懂的 > 參考文件:https://autofaccn.readthedocs.io/en/latest/integration/aspnetcore.html#asp-net-core-3-0-and-generic-hosting 當然`Autofac`的應用遠不止這些,還有一個比原來好的就是可以實現AOP~ ![](https://img2020.cnblogs.com/blog/1006210/202007/1006210-20200714200045495-1320486