ASP.Net Core 3.1 With Autofac ConfigureServices returning an System.IServiceProvider isn't supported.
阿新 • • 發佈:2020-07-17
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