.NET Core 2.0 IOptions appsettings null问题

时间:2018-02-07 12:04:37

标签: .net-core structuremap appsettings

我有一个.NET Core 2.0应用程序,它使用IOptions<>将配置部分注入到我的各种服务中。如果我在visual studio和大多数环境(舞台/制作等)中运行应用程序,工作正常。出于某种原因,在我的机器上本地运行构建的应用程序会导致出现错误,就好像注入的配置类具有NULL值一样。

代码:

Startup.cs (使用structuremap注入其他服务)

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    // This method gets called by the runtime. Use this method to add services to the container.
    public IServiceProvider ConfigureServices(IServiceCollection services)
    {
        services.AddSingleton(Configuration);
        services.AddOptions();
        services.Configure<RedisCacheConfiguration>(c => Configuration.GetSection("RedisCacheConfiguration").Bind(c));
        return ConfigureIoC(services);
    }

    private IServiceProvider ConfigureIoC(IServiceCollection services)
    {
        var container = new Container();

        container.Configure(config =>
        {
            config.Scan(_ =>
            {
                _.AssemblyContainingType(typeof(Startup));
                _.WithDefaultConventions();
            });
        });
        container.Populate(services);
        return container.GetInstance<IServiceProvider>();
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        app.UseMvc();
    }
}

appsettings.json

{
  "RedisCacheConfiguration": {
    "RedisAddress": "redis.server:6379"
  }
}

RedisCacheConnectionFactory.cs

public class RedisCacheConnectionFactory
{
    private readonly ConnectionMultiplexer _connection;

    public RedisCacheConnectionFactory(IOptions<RedisCacheConfiguration> configAssessor)
    {
        var configuration = configAssessor.Value;
        var redisAddress = configuration.RedisAddress;

        if (_connection == null || !_connection.IsConnected || !_connection.GetDatabase().IsConnected(default(RedisKey)))
        {
            var addressChunks = redisAddress.Split(':');
            var address = addressChunks[0];
            var port = int.Parse(addressChunks[1]);
            var configurationOptions = new ConfigurationOptions
            {
                AbortOnConnectFail = false,
                ConnectTimeout = 600,
            };
            configurationOptions.EndPoints.Add(new DnsEndPoint(address, port));

            _connection = ConnectionMultiplexer.Connect(configurationOptions);
        }
    }

    public ConnectionMultiplexer Connection => _connection;
}

错误

Hosting environment: Development
Content root path: C:\Work\MyApi\MyApi
Now listening on: http://localhost:57070
Application started. Press Ctrl+C to shut down.
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
      Request starting HTTP/1.1 POST http://localhost:57070/outboundpayload application/json 1141
info: MyApi.Authentication.MyApiAuthHandler[8]
      AuthenticationScheme: MyApi was successfully authenticated.
info: Microsoft.AspNetCore.Authorization.DefaultAuthorizationService[1]
      Authorization was successful for user: (null).
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
      Executed action MyApi.Controllers.OutboundPayloadController.Post (MyApi) in 170.5965ms
fail: Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware[0]
      An unhandled exception has occurred while executing the request
StructureMap.Building.StructureMapBuildException: Error while building type MyApi.Infrastructure.Factories.RedisCacheConnectionFactory.  See the inner exception for details
1.) new RedisCacheConnectionFactory(*Default of IOptions<RedisCacheConfiguration>*)
2.) MyApi.Infrastructure.Factories.RedisCacheConnectionFactory
3.) Instance of MyApi.Infrastructure.Factories.RedisCacheConnectionFactory
4.) new RedisCacheProvider(*Default of RedisCacheConnectionFactory*, *Default of IOptions<RedisCacheConfiguration>*)
5.) MyApi.Infrastructure.Providers.RedisCacheProvider
6.) Instance of MyApi.Domain.Contracts.Providers.ICacheProvider (MyApi.Infrastructure.Providers.RedisCacheProvider)
7.) new EncryptedLeadCacheManager(*Default of ICacheProvider*, *Default of IEnvironmentWrapper*, *Default of IAesCryptographyService*)
8.) MyApi.Domain.Managers.EncryptedLeadCacheManager
9.) Instance of MyApi.Domain.Contracts.Managers.ICacheManager (MyApi.Domain.Managers.EncryptedLeadCacheManager)
10.) new OutboundLeadService(*Default of IUidService*, *Default of ICacheManager*)
11.) MyApi.Domain.Services.OutboundLeadService ('MyApi.Domain.Services.OutboundLeadService, MyApi.Domain, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null')
12.) Instance of MyApi.Domain.Contracts.Services.IOutboundLeadService ('MyApi.Domain.Services.OutboundLeadService, MyApi.Domain, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null')
13.) new OutboundPayloadFactory(*Default of ICertificateRepository*, *Default of IAes128Encryptor*, *Default of IQueryStringHelper*, *Default of IOutboundLeadService*, *Default of ILogger*, *Default of IMapProcessedLeadToIssuerLeadDto*)
14.) MyApi.Domain.Factories.OutboundPayloadFactory ('MyApi.Domain.Factories.OutboundPayloadFactory, MyApi.Domain, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null')
15.) Instance of MyApi.Domain.Contracts.Factories.IOutboundPayloadFactory ('MyApi.Domain.Factories.OutboundPayloadFactory, MyApi.Domain, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null')
16.) Container.GetInstance(MyApi.Domain.Contracts.Factories.IOutboundPayloadFactory)
17.) Container.TryGetInstance(MyApi.Domain.Contracts.Factories.IOutboundPayloadFactory)
 ---> System.NullReferenceException: Object reference not set to an instance of an object.
   at MyApi.Infrastructure.Factories.RedisCacheConnectionFactory..ctor(IOptions`1 configAssessor) in C:\Work\MyApi\MyApi\MyApi.Infrastructure\Factories\RedisCacheConnectionFactory.cs:line 19
   at lambda_method(Closure , IBuildSession , IContext )
   --- End of inner exception stack trace ---
   at lambda_method(Closure , IBuildSession , IContext )
   at StructureMap.Building.BuildPlan.Build(IBuildSession session, IContext context)
   at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory)
   at StructureMap.SessionCache.GetObject(Type pluginType, Instance instance, ILifecycle lifecycle)
   at StructureMap.SessionCache.GetDefault(Type pluginType, IPipelineGraph pipelineGraph)
   at StructureMap.Container.GetInstance(Type pluginType)
   at StructureMap.Container.TryGetInstance(Type pluginType)
   at Microsoft.Extensions.Internal.ActivatorUtilities.GetService(IServiceProvider sp, Type type, Type requiredBy, Boolean isDefaultParameterRequired)
   at lambda_method(Closure , IServiceProvider , Object[] )
   at Microsoft.AspNetCore.Mvc.Controllers.ControllerActivatorProvider.<>c__DisplayClass4_0.<CreateActivator>b__0(ControllerContext controllerContext)
   at Microsoft.AspNetCore.Mvc.Controllers.ControllerFactoryProvider.<>c__DisplayClass5_0.<CreateControllerFactory>g__CreateController0(ControllerContext controllerContext)
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeInnerFilterAsync>d__14.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.<InvokeNextResourceFilter>d__22.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Rethrow(ResourceExecutedContext context)
   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.<InvokeFilterPipelineAsync>d__17.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.<InvokeAsync>d__15.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.AspNetCore.Builder.RouterMiddleware.<Invoke>d__4.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.<Invoke>d__6.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.<Invoke>d__7.MoveNext()
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
      Request finished in 474.7396ms 500 text/html; charset=utf-8

IOptions似乎已注入,但值为空,请参阅Inner Exception

  

System.NullReferenceException:未将对象引用设置为对象的实例。          在MyApi.Infrastructure.Factories.RedisCacheConnectionFactory..ctor(IOptions`1 configAssessor)中的C:\ Work \ MyApi \ MyApi \ MyApi.Infrastructure \ Factories \ RedisCacheConnectionFactory.cs:第19行

一旦我在此类中进行了空处理,错误就会更改为使用IOptions<>注入配置的下一个实例。

任何人都知道我为什么会出现这种行为?

0 个答案:

没有答案