我有一个.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<>
注入配置的下一个实例。
任何人都知道我为什么会出现这种行为?