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
。我們可以先看一下部分程式碼:
public IServiceProvider ConfigureServices(IServiceCollection services)
{
services.AddMvc();
//xxxxxx你的其他程式碼 省略...........
//用Autofac來替換IOC容器 返回值由 void 修改為 IServiceProvider
var containerBuilder = new ContainerBuilder();
containerBuilder.RegisterModule<CustomAutofacModule>();
containerBuilder.Populate(services);
var container = containerBuilder.Build();
//將當前的容器儲存起來,用於後續使用
AutofacHelper.Container = container;
return new AutofacServiceProvider(container);
}
完整程式碼可以參考我之前的開源專案: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專案
效果圖
Services
建立完成後我們先建立資料夾Services
,用來測試使用。
在Services
資料夾下建立Iservice
namespace DotNetCore3AutoFac.Services
{
public interface IService
{
string SayHi();
}
}
然後建立兩個Iservice
的實現類OneService
、TwoService
namespace DotNetCore3AutoFac.Services
{
public class OneService:IService
{
public string SayHi()
{
return "One Say Hi";
}
}
}
namespace DotNetCore3AutoFac.Services
{
public class TwoService:IService
{
public string SayHi()
{
return "Two Say Hi";
}
}
}
Autofac
建立Autofac
資料夾,在該資料夾下建立CustomAutofacModule
using Autofac;
using DotNetCore3AutoFac.Services;
namespace DotNetCore3AutoFac.Autofac
{
public class CustomAutofacModule : Module
{
/// <summary>
/// AutoFac註冊類
/// </summary>
/// <param name="builder"></param>
protected override void Load(ContainerBuilder builder)
{
builder.RegisterType<OneService>().As<IService>();
}
}
}
我們先用OneService
去實現,當然,正常這裡會有很多很多的程式碼~
修改Startup
和Program
當然,需要安裝Autofac的包:
Autofac
&Autofac.Extensions.DependencyInjection
前序工作都完成了,我們來改最重要的,首先修改我們的Program
,增加UseServiceProviderFactory(new AutofacServiceProviderFactory())
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>();
});
}
}
然後我們修改Startup
1、增加屬性
AutofacContainer
2、增加方法
ConfigureContainer
它在ConfigureServices
之後執行3、給屬性賦值(可選)
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
執行,斷點看下結果是否正確
修改下實現類,也是正確的~
總結
其實很多官方文件都講述了,因為自己近期打算把原來的專案LJD.APP:https://github.com/jellydong/LJDAPP升級到.Net Core 3.1上,當然是一個簡化版本https://github.com/jellydong/Jelly.Simple。
所以不要怕英文,翻譯外掛那麼好用,基本都能看懂的
當然Autofac
的應用遠不止這些,還有一個比原來好的就是可以實現AOP~