问题
(This question is similar to ASP.NET Core MvcOptions dependency injection without modified closure? However, I struggle to apply the solution of that question to this one.)
In my ASP.NET Core 1.1.3 project, I currently inject an ITraceWriter
dependency into MvcJsonOptions
in the ConfigureServices
method in the following way:
public override IServiceProvider ConfigureServices(IServiceCollection services)
{
services.AddProjectSpecificStuff();
ITraceWriter traceWriter = null;
services.AddMvc().AddJsonOptions(options =>
{
options.SerializerSettings.TraceWriter = traceWriter;
});
var provider = base.ConfigureServices(services);
traceWriter = provider.GetService<ITraceWriter>();
return provider;
}
This works, but causes code analyzers such as ReSharper to complain about access to modified closure.
Is there an alternative to achieve the same dependency injection without using modified closure?
回答1:
You can likely postpone the assignment to .Configure
method, it should work.
public override IServiceProvider ConfigureServices(IServiceCollection services)
{
services.AddProjectSpecificStuff();
ITraceWriter traceWriter = null;
services.AddMvc().AddJsonOptions(options =>
{
...
// other options here
});
return base.ConfigureServices(services);
}
public void Configure(IApplicationBuilder app, ITraceWriter traceWriter, IOptions<MvcJsonOptions> jsonOptions)
{
services.AddMvc().AddJsonOptions(options =>
{
options.SerializerSettings.TraceWriter = provider.GetService<ITraceWriter>();
});
}
This will work for as long as your dependencies (like IOptions<MvcJsonOptions>
and ITraceWriter
are singletons.
Word of warning
However, this behavior may change in future, as some plans/ideas were on the ASP.NET Core GitHub issues, that the ASP.NET Core may change this to create an implicitly scoped context which is used during .Configure
, it may or may not break the above code (if it ever comes).
But you may want consider to directly instantiate the ITraceWriter
and pass it as instance to the IoC container, such as
ITraceWriter traceWriter = new TraceWriter(/* other dependencies */);
services.AddSingleton<ITraceWriter>(traceWriter);
It's okay to compose it in the composition root, as long as it's a singleton.
Or alternatively you choose this brute and somewhat ugly solution and instantiate MvcJsonOptions
via factory method:
services.AddSingleton<IOptions<MvcJsonOptions>>(provider => Options.Create(new MvcJsonOptions
{
SerializerSettings.TraceWriter = provider.GetService<ITraceWriter>()
}));
Then it's pretty ugly (though you could hide that behind an extension method) and you may override defaults set by the mddleware/extension method.
来源:https://stackoverflow.com/questions/45826530/asp-net-core-mvcjsonoptions-dependency-injection-without-modified-closure