Reputation: 2026
I have implemented the IndexBuilderSettings which is a model for some Services, such like when I created one for that will like below
services.AddSingleton<SearchBrandBuilder>()
.Configure<IndexBuilderSettings>((settings) =>
{
Configuration.GetSection("SearchBrandConfig").Bind(settings);
});
And the SearchBrandBuilder
is using IOptions construction
public class SearchBrandBuilder : SearchIndexBuilder<SearchBrandModel>
{
public SearchBrandBuilder(IOptions<IndexBuilderSettings> opts);
}
But the problem is when I have to create another one, like SearchUnitBuilder
with the same IOptions constructor, the Configure()
seems can't help because it will be overwritten due to its singleton pattern, please noticed that I would like to keep the settings json like this
"SearchBrandConfig": {
"AdminApiKey": "456",
"IndexName": "new-brands",
"SearchServiceName": "search_name"
},
"SearchUnitConfig": {
"AdminApiKey": "123",
"IndexName": "new-units",
"SearchServiceName": "search_name"
},
I also don't want to rewrite the library model as IOptionsSnapshot which will inject via the name to distinguish. https://andrewlock.net/using-multiple-instances-of-strongly-typed-settings-with-named-options-in-net-core-2-x/
So the guide from link would be like this, but I won't prefer
public void ConfigureServices(IServiceCollection services)
{
services.Configure<SlackApiSettings>("Dev", Configuration.GetSection("SlackApi:DevChannel"));
services.Configure<SlackApiSettings>("General", Configuration.GetSection("SlackApi:GeneralChannel"));
services.Configure<SlackApiSettings>("Public", Configuration.GetSection("SlackApi:PublicChannel"));
}
So, I would like to use Configuration as temporary in the Startup, I found out that it could be done by below code, a little bit workaround
services.AddSingleton<SearchBrandBuilder>(
new SearchBrandBuilder(Options.Create(Configuration.GetSection("SearchBrandConfig").Get<IndexBuilderSettings>())));
services.AddSingleton<SearchUnitBuilder>(
new SearchUnitBuilder(Options.Create(Configuration.GetSection("SearchUnitConfig").Get<IndexBuilderSettings>())));
I see it is a acceptance solution, but I would like to ask if whether any better solution for that? Something like a built-in function:
services.AddSingletonWithSetting<SearchUnitBuilder, IndexBuilderSettings>(settings =>
Configuration.GetSection("SearchUnitConfig").Bind(settings));
Or any regular solution for dealing this case?
Upvotes: 2
Views: 4011
Reputation: 81573
You can also use named options with IOptionsSnapshot
... I'm personally not huge fan, however they are useful in certain use cases. ¯\_(ツ)_/¯
Given
services.Configure<Config>("SomeConfig", Configuration.GetSection("SomeSection"));
services.Configure<Config>("AnotherConfig", Configuration.GetSection("AnotherSection"));
Implementation
public class SomeClass
{
...
public SomeClass(IOptionsSnapshot<Config> namedOptionsAccessor)
{
_config1 = namedOptionsAccessor.Get("SomeConfig");
_config2 = namedOptionsAccessor.Get("AnotherConfig");
}
...
Additional Resources
Upvotes: 3
Reputation: 143243
Personally I prefer creating child config instances inheriting from base ine containing all properties:
public class SearchBrandConfig : IndexBuilderSettings {}
public class SearchUnitConfig : IndexBuilderSettings {}
And then registering and resolving them accrodingly:
services.Configure<SearchBrandConfig>(Configuration.GetSection("SearchBrandConfig"));
services.Configure<SearchUnitConfig>(Configuration.GetSection("SearchUnitConfig "));
And
public class SearchBrandBuilder : SearchIndexBuilder<SearchBrandModel>
{
public SearchBrandBuilder(IOptions<SearchBrandConfig> opts);
}
public class SearchUnitBuilder : SearchIndexBuilder<SearchUnitModel>
{
public SearchUnitBuilder(IOptions<SearchUnitConfig> opts);
}
If there are a lot of such builders - you can even partly automate registration with some reflection.
Upvotes: 2