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中我們一般是把StartupConfigureServices方法返回值型別改為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的實現類OneServiceTwoService

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去實現,當然,正常這裡會有很多很多的程式碼~

修改StartupProgram

當然,需要安裝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。

所以不要怕英文,翻譯外掛那麼好用,基本都能看懂的

參考檔案:https://autofaccn.readthedocs.io/en/latest/integration/aspnetcore.html#asp-net-core-3-0-and-generic-hosting

當然Autofac的應用遠不止這些,還有一個比原來好的就是可以實現AOP~