简体   繁体   English

如何从 .NET Core 3.1 中的 Autofac 容器解析已注册的依赖项

[英]How can I resolve a registered Dependency from an Autofac Container in .NET Core 3.1

There's a project I'm trying to upgrade to .NET Core 3.1 from 2.2.有一个项目我正在尝试从 2.2 升级到 .NET Core 3.1。 My major issue is at the startup.cs where I'm registering dependencies with Autofac.我的主要问题是在 startup.cs 中,我正在向 Autofac 注册依赖项。 I have studied the documentation for registering dependencies in 3.0 and I understand it.我已经研究了在 3.0 中注册依赖项的文档并且我理解它。 But there is a requirement in ConfigureServices method to register an object as an instance and it requires the container to resolve a registered service in the same method as seen in the code below但是ConfigureServices方法要求将对象注册为实例,并且它要求容器以与下面代码中所示相同的方法解析注册的服务

Startup.cs (2.2)启动.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);
}

In .net core 3.1, I couldn't find a clear means of replicating the above with the new Autofac approach.在 .net core 3.1 中,我找不到使用新的 Autofac 方法复制上述内容的明确方法。

Startup (3.1)启动 (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 throws null reference at runtime. this.AutofacContainer在运行时抛出空引用。 I am not surprised by this because ConfigureServices executes before Configure method where I get references to the registered dependencies in the container.我对此并不感到惊讶,因为ConfigureServicesConfigure方法之前执行,在那里我可以获取对容器中已注册依赖项的引用。 I can't seem to find a way to resolve IHttpContextAccessor from the container in ConfigureServices and use it as it is in netcore 2.2.我似乎无法找到一种方法来从ConfigureServices的容器解析IHttpContextAccessor并像在 netcore 2.2 中一样使用它。

For clarity, Please see how the executionContextAccessor is used in the class that does the initialization as done in netcoreapp2.2:为了清楚起见,请参阅如何executionContextAccessor是,做在netcoreapp2.2完成初始化类的使用:

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();
        }
    }
}

You could do the following in Configure although I wouldn't recommend it as you're splitting the responsibility of registering your dependencies across multiple parts of your startup.您可以在Configure执行以下Configure尽管我不建议这样做,因为您将在启动的多个部分中注册依赖项的责任分开。 This will resolve the IHttpContextAccessor through IApplicationBuilder.GetServce<TService>() which you can then use for subsequent registrations.这将通过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);
        }

Likewise, you could also resolve the IExecutionContextAccessor in order to add registrations like so.同样,您也可以解析 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);
        }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何从 autofac 容器解析依赖项(在嵌套的 LifetimeScope 中注册) - How can a dependency (registered in nested LifetimeScope) be resolved from autofac container 如何从Asp.net核心依赖注入中注册的子类解析父类实例 - How to resolve parent class instance from registered child class in Asp.net core dependency injection 如何解决Autofac中的依赖关系? - How to Resolve dependency in Autofac? 在 .NET Core 3 和 3.1 中设置 Autofac - Setup Autofac in .NET Core 3 and 3.1 如何从 ASP.NET Core 3.1 中的 EntityFrameworkCore 3 中删除依赖项 - How to remove dependency from EntityFrameworkCore 3 in ASP.NET core 3.1 将所有注册的服务从 ASP.NET Core IOC 容器解析到单个接口 - Resolve all registered services to a single interface from ASP.NET Core IOC container Autofac 作为 AWS 中的 IoC 容器 Lambda 无服务器 ASP.NET Core 3.1 Web ZDB974238714CA8DE64FZACE7 - Autofac as IoC container in AWS Lambda Serverless ASP.NET Core 3.1 Web API 我应该如何通过Autofac.Dependency注入库将参数传递给Autofac容器以实现自动依赖关系解析 - How should I pass parameters to the Autofac container for auto dependency resolution via Autofac.Dependency injection lib 如何从解析依赖项将参数传递给 Autofac 模块 - How to pass parameter to an Autofac Module from a resolve dependency 如何在运行时更新Autofac容器中的注册实例 - How to update registered instances in Autofac container in runtime
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM