-
-
Save ericsampson/bb37bd6da0748af2e928ee750563452a to your computer and use it in GitHub Desktop.
| // I have a service that needs to be initialized with a FooOptions and then added to the DI container. | |
| // I also want to have IOptions<FooOptions> in the DI container to allow injection in other methods. | |
| // How should I write my AddFoo extension method to support this? | |
| public void ConfigureServices(IServiceCollection services) | |
| { | |
| services.AddFoo(fooOptions => | |
| { | |
| configuration.GetSection("FooOptions").Bind(fooOptions) | |
| fooOptions.param = "override"; | |
| }); | |
| } | |
| namespace Microsoft.Extensions.DependencyInjection | |
| { | |
| public static class MyFooExtensions | |
| { | |
| public static IServiceCollection AddFoo(this IServiceCollection services, | |
| Action<FooOptions> setupOptions) | |
| { | |
| services.Configure<FooOptions>(setupOptions); | |
| services.AddSingleton<IFoo>(sp => | |
| { | |
| var options = sp.GetRequiredService<IOptions<FooOptions>>(); | |
| return new FooFactory(options.Value); | |
| }; | |
| return services; | |
| } | |
| } | |
| } |
@andrewlock, I just updated the gist to add line 31 - the motivation for my original question is that an instance of FooOptions is needed inside AddFoo, so I don't think that's going to work.
Sorry if that wasn't clear :) This just seems like a common scenario, so I must be missing something...
Yeah, unfortunately, you're kinda screwed in that case 🙁
Basically, requiring concrete IOptions<> in the AddFoo() method is not the recommended pattern, for exactly this reason! But if that's what it is, there's not a lot you can do...
In the few cases I've run into this I have just manually bound the configuration instead. It's not ideal, and means you can't use the full options pattern, but it may do:
public void ConfigureServices(IServiceCollection services)
{
var fooOptions = new FooOptions();
Configuration.Bind("FooOptions", fooOptions);
services.AddFoo(fooOptions);
}Rich Strahl has a nice post about this here: https://weblog.west-wind.com/posts/2017/dec/12/easy-configuration-binding-in-aspnet-core-revisited
@andrewlock, argh I'm an idiot. The signature is FooFactory(FooOptions options), not an IOptions<FooOptions>, if that helps.
I think I've revised the AddFoo() code in a way that should work now?? Or not...
I found a helpful blog post from @TsuyoshiUshio that gave me the idea:
https://medium.com/@tsuyoshiushio/servicecollection-di-with-optional-settings-fc4ee46984d1
@ericsampson That looks very similar to my suggestion, with a slight tweak. I don't think your suggestion will quite work though. Try this instead:
public void ConfigureServices(IServiceCollection services)
{
services.AddFoo(fooOptions =>
{
configuration.GetSection("FooOptions").Bind(fooOptions)
fooOptions.param = "override";
});
}Thanks again @andrewlock, I'll give this all a go. Really appreciate the help :)
Given that
AddFoo()is just callingservices.Configure<FooOptions>(options), then you can just ignore the configuration:e.g.: