有一个项目正在尝试从2.2升级到.NET Core 3.1。我的主要问题是在startup.cs上,我正在其中向Autofac注册依赖项。我已经研究了在3.0中注册依赖项的文档,并且我理解它。但是ConfigureServices
方法中要求将对象注册为实例,并且要求容器以与下面的代码相同的方法解析注册的服务
Startup.cs(2.2)
public IServiceProvider ConfigureServices(IServiceCollection services)
{
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddSingleton<IExecutionContextAccessor, ExecutionContextAccessor>();
//other services registered
return CreateAutofacServiceProvider(services);
}
private IServiceProvider CreateAutofacServiceProvider(IServiceCollection services)
{
var containerBuilder = new ContainerBuilder();
containerBuilder.Populate(services);
containerBuilder.RegisterModule(new MyModule());
var container = containerBuilder.Build();
var httpContextAccessor = container.Resolve<IHttpContextAccessor>();
var executionContextAccessor = new ExecutionContextAccessor(httpContextAccessor);
var emailsConfiguration = new EmailsConfiguration(_configuration["EmailsConfiguration:FromEmail"]);
// executionContextAccessor is used to initialize some modules here
return new AutofacServiceProvider(container);
}
在.net core 3.1中,我找不到使用新的Autofac方法复制以上内容的明确方法。
启动(3.1)
public ILifetimeScope AutofacContainer { get; private set; }
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddSingleton<IExecutionContextAccessor, ExecutionContextAccessor>();
// other services registered
var httpContextAccessor = this.AutofacContainer.Resolve<IHttpContextAccessor>();
var executionContextAccessor = new ExecutionContextAccessor(httpContextAccessor);
var emailsConfiguration = new EmailsConfiguration(_configuration["EmailsConfiguration:FromEmail"]);
// executionContextAccessor is used to initialize some modules here
}
public void ConfigureContainer(ContainerBuilder containerBuilder)
{
containerBuilder.RegisterModule(new MyModule());
}
public void Configure(IApplicationBuilder app, IHostEnvironment env)
{
this.AutofacContainer = app.ApplicationServices.GetAutofacRoot();
// other stuff
}
this.AutofacContainer
在运行时引发空引用。我对此并不感到惊讶,因为ConfigureServices
在Configure
方法执行之前得到了容器中已注册的依赖项的引用。我似乎找不到一种方法来从IHttpContextAccessor
的容器中解析ConfigureServices
并像在netcore 2.2中一样使用它。
为清楚起见,请参见在netcoreapp2.2中完成初始化的类中如何使用executionContextAccessor
:
public class ModuleStartup
{
private static IContainer _container;
public static void Initialize(
IExecutionContextAccessor executionContextAccessor,
EmailsConfiguration emailsConfiguration)
{
ConfigureCompositionRoot(
executionContextAccessor,
emailsConfiguration);
}
private static void ConfigureCompositionRoot(
IExecutionContextAccessor executionContextAccessor,
EmailsConfiguration emailsConfiguration)
{
var containerBuilder = new ContainerBuilder();
containerBuilder.RegisterModule(new EmailModule(emailsConfiguration));
containerBuilder.RegisterInstance(executionContextAccessor);
_container = containerBuilder.Build();
ModuleCompositionRoot.SetContainer(_container);
}
Internal static class ModuleCompositionRoot
{
private static IContainer _container;
internal static void SetContainer(IContainer container)
{
_container = container;
}
internal static ILifetimeScope BeginLifetimeScope()
{
return _container.BeginLifetimeScope();
}
}
}
答案 0 :(得分:0)
您可以在 Configure
中执行以下操作,但我不建议这样做,因为您将注册依赖项的责任分散到启动的多个部分。这将通过 IApplicationBuilder.GetServce<TService>()
解析 IHttpContextAccessor,然后您可以将其用于后续注册。
public void Configure(IApplicationBuilder app, IHostEnvironment env)
{
var httpContextAccessor = app.ApplicationServices.GetService<IHttpContextAccessor>();
var executionContextAccessor = new ExecutionContextAccessor(httpContextAccessor);
var emailsConfiguration = new EmailsConfiguration(_configuration["EmailsConfiguration:FromEmail"]);
ModuleStartup.Initialize(executionContextAccessor, emailsConfiguration);
}
同样,您也可以解析 IExecutionContextAccessor 以添加这样的注册。
public void Configure(IApplicationBuilder app, IHostEnvironment env)
{
var httpContextAccessor = app.ApplicationServices.GetService<IHttpContextAccessor>();
var executionContextAccessor = new ExecutionContextAccessor(httpContextAccessor);
var fooToRegister = new Foo(executionContextAccessor);
var registration = RegistrationBuilder
.ForDelegate<IAnotherInterface>((c, p) => fooToRegister)
.InstancePerLifetimeScope()
.CreateRegistration();
app.ApplicationServices
.GetAutofacRoot().ComponentRegistry
.Register(registration);
}