繁体   English   中英

带ASP.Net Core 2.0 IOptions的简单注入器快照注入

[英]Simple Injector w/ ASP.Net Core 2.0 IOptionsSnapshot injection

我正在尝试在错误#429中提出的建议,并且遇到了他在该位置报告的错误,但是从没有提供堆栈跟踪。 我还阅读并使用了直到最近的有关不使用IOptions和相关类的指南。 当我们在Azure中运行某些东西时,确实需要IOptionsSnapshot ,并且当我们达到极限时,需要能够即时打开/关闭选项,并且重启服务不是选项,因为它最多需要5个最初需要几分钟,这是由于我们需要一些第三方产品。

这是我们设置的内容:

  • 简单注射器4.3.0
  • .NET Core 2.0 Web API

接口ISearchSettings >类SearchSettings
(基本上,这里的所有属性,除了1个布尔值,我们都可以根据需要单身。一个布尔值有点告诉我们是使用内部搜索还是使用天蓝色搜索)

应用启动时,出现以下错误:

System.InvalidOperationException:配置无效。 创建类型为IOptionsSnapshot <SearchSettings>的实例失败。 类型为IOptionsSnapshot <SearchSettings>的注册委托引发了异常。 无法从ASP.NET Core请求服务请求服务'IOptionsSnapshot <SearchSettings>。 请确保在活动HTTP请求的上下文中调用此方法。

在“配置服务”中:

services.AddOptions();  
services.Configure<ISearchSettings>(
    this.Configuration.GetSection("AzureSearchSettings"));  
services.Configure<SearchSettings>(
    this.Configuration.GetSection("AzureSearchSettings"));  
// The next line was added trying some other suggestions from similar
// errors. It didn't resolve the issue  
services.AddScoped(
    cfg => cfg.GetService<IOptionsSnapshot<SearchSettings>>().Value);  
...  
services.AddMvc();  
...  
IntegrateSimpleInjector();  

在IntegrateSimpleInjector中:

this.container.Options.DefaultScopedLifestyle =
    new AsyncScopedLifestyle();

services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddSingleton<IControllerActivator>(
    new SimpleInjectorControllerActivator(this.container));
services.AddSingleton<IViewComponentActivator>(
    new SimpleInjectorViewComponentActivator(this.container));

services.EnableSimpleInjectorCrossWiring(this.container);
services.UseSimpleInjectorAspNetRequestScoping(this.container);

在InitializeContainer中:

// I have tried both Lifestyle Transient and Scoped
this.container.Register<IOptionsSnapshot<SearchSettings>>(
    () => app.GetRequestService<IOptionsSnapshot<SearchSettings>>(),
    Lifestyle.Transient);
...
this.container.AutoCrossWireAspNetComponents(app);

堆栈跟踪:

at SimpleInjector.SimpleInjectorAspNetCoreIntegrationExtensions.GetRequestServiceProvider(IApplicationBuilder builder, Type serviceType)
at SimpleInjector.SimpleInjectorAspNetCoreIntegrationExtensions.GetRequestService[T](IApplicationBuilder builder)
at QuotingService.Startup.<>c__DisplayClass9_0.<InitializeContainer>b__0() in E:\Repos\QuotingService\QuotingService\Startup.cs:line 299
at lambda_method(Closure )
at SimpleInjector.InstanceProducer.BuildAndReplaceInstanceCreatorAndCreateFirstInstance()
at SimpleInjector.InstanceProducer.GetInstance()
--- End of inner exception stack trace ---
at SimpleInjector.InstanceProducer.GetInstance()
at SimpleInjector.InstanceProducer.VerifyInstanceCreation()
--- End of inner exception stack trace ---
at SimpleInjector.InstanceProducer.VerifyInstanceCreation()
at SimpleInjector.Container.VerifyInstanceCreation(InstanceProducer[] producersToVerify)
at SimpleInjector.Container.VerifyInternal(Boolean suppressLifestyleMismatchVerification)
at SimpleInjector.Container.Verify()
at QuotingService.Startup.Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, IApplicationLifetime appLifetime) in E:\Repos\QuotingService\QuotingService\Startup.cs:line 229
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at Microsoft.AspNetCore.Hosting.ConventionBasedStartup.Configure(IApplicationBuilder app)
at Microsoft.AspNetCore.Hosting.Internal.WebHost.BuildApplication()

关于什么需要更改才能使此工作有任何想法?
感谢您提供的出色产品以及所提供的任何帮助。

您应该避免在简单的Injector注册的委托中调用GetRequestService ,因为这种调用要求存在一个活动的HTTP请求,该请求在应用程序启动期间将不可用。

而是依靠AutoCrossWireAspNetComponents从ASP.NET Core获取IOptionsSnapshot<SearchSettings>

但是,要使其正常工作,您需要调用services.Configure<SearchSettings>

这是一个有效的配置:

public class Startup
{
    private Container container = new Container();

    public Startup(IHostingEnvironment env)
    {
        var builder = new ConfigurationBuilder()
            .SetBasePath(env.ContentRootPath)
            .AddJsonFile("appsettings.json");
        this.Configuration = builder.Build();
    }

    public IConfigurationRoot Configuration { get; }

    public void ConfigureServices(IServiceCollection services)
    {
        // ASP.NET default stuff here
        services.AddMvc();

        this.IntegrateSimpleInjector(services);

        services.Configure<SearchSettings>(
            Configuration.GetSection("SearchSettings"));
    }

    private void IntegrateSimpleInjector(IServiceCollection services)
    {
        container.Options.DefaultScopedLifestyle = new AsyncScopedLifestyle();

        services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();

        services.AddSingleton<IControllerActivator>(
            new SimpleInjectorControllerActivator(container));

        services.EnableSimpleInjectorCrossWiring(container);
        services.UseSimpleInjectorAspNetRequestScoping(container);
    }

    public void Configure(IApplicationBuilder app)
    {
        container.AutoCrossWireAspNetComponents(app);
        container.RegisterMvcControllers(app);

        container.Verify();

        // ASP.NET default stuff here
        app.UseMvc(routes =>
        {
            routes.MapRoute(
                name: "default",
                template: "{controller=Home}/{action=Index}/{id?}");
        });
    }
}

使用此配置,您可以在所有位置注入IOptionsSnapshot<T> 例如在您的HomeController内部:

public class HomeController : Controller
{
    private readonly IOptionsSnapshot<SearchSettings> snapshot;

    public HomeController(
        IOptionsSnapshot<SearchSettings> snapshot)
    {
        this.snapshot = snapshot;
    }
}

暂无
暂无

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM