Adding extension methods to IServiceCollection in ASP.NET Core
Clash Royale CLAN TAG#URR8PPP
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;
up vote
4
down vote
favorite
I have the following extension method to add themes support to my application:
public static void AddThemes(this IServiceCollection services, Action<ThemesOptions> setup)
services.Configure(setup);
Where ThemesOptions
is defined as:
public class ThemesOptions
public IEnumerable<string> Themes get; set;
Now in my application's startup ConfigureServices
method I can say:
services.AddThemes(options =>
options.Themes = Configuration.GetSection("Themes").Get<ThemesOptions>().Themes;
);
I'm not sure that I like that I have to set every property for the options. Alternatively I tried:
services.AddThemes(options =>
options = Configuration.GetSection("Themes").Get<ThemesOptions>();
);
And:
services.AddThemes(options => Configuration.GetSection("Themes"));
However when I inject IOptions<ThemesOptions>
the Themes
property is null.
An alternative to I changed my extension method to:
public static void AddThemes(this IServiceCollection services, IConfiguration configuration)
services.Configure<ThemesOptions>(configuration.GetSection("Themes"));
Now I can say the following within my application's Startup ConfigureServices
method:
services.AddThemes(Configuration);
This worked fine, however, I feel the problem with this approach is that the extension method only allows the options to be set from the configuration.
I'd appreciate it if someone could confirm whether my first solution is correct and if it can be improved upon.
c# dependency-injection asp.net-core
add a comment |Â
up vote
4
down vote
favorite
I have the following extension method to add themes support to my application:
public static void AddThemes(this IServiceCollection services, Action<ThemesOptions> setup)
services.Configure(setup);
Where ThemesOptions
is defined as:
public class ThemesOptions
public IEnumerable<string> Themes get; set;
Now in my application's startup ConfigureServices
method I can say:
services.AddThemes(options =>
options.Themes = Configuration.GetSection("Themes").Get<ThemesOptions>().Themes;
);
I'm not sure that I like that I have to set every property for the options. Alternatively I tried:
services.AddThemes(options =>
options = Configuration.GetSection("Themes").Get<ThemesOptions>();
);
And:
services.AddThemes(options => Configuration.GetSection("Themes"));
However when I inject IOptions<ThemesOptions>
the Themes
property is null.
An alternative to I changed my extension method to:
public static void AddThemes(this IServiceCollection services, IConfiguration configuration)
services.Configure<ThemesOptions>(configuration.GetSection("Themes"));
Now I can say the following within my application's Startup ConfigureServices
method:
services.AddThemes(Configuration);
This worked fine, however, I feel the problem with this approach is that the extension method only allows the options to be set from the configuration.
I'd appreciate it if someone could confirm whether my first solution is correct and if it can be improved upon.
c# dependency-injection asp.net-core
add a comment |Â
up vote
4
down vote
favorite
up vote
4
down vote
favorite
I have the following extension method to add themes support to my application:
public static void AddThemes(this IServiceCollection services, Action<ThemesOptions> setup)
services.Configure(setup);
Where ThemesOptions
is defined as:
public class ThemesOptions
public IEnumerable<string> Themes get; set;
Now in my application's startup ConfigureServices
method I can say:
services.AddThemes(options =>
options.Themes = Configuration.GetSection("Themes").Get<ThemesOptions>().Themes;
);
I'm not sure that I like that I have to set every property for the options. Alternatively I tried:
services.AddThemes(options =>
options = Configuration.GetSection("Themes").Get<ThemesOptions>();
);
And:
services.AddThemes(options => Configuration.GetSection("Themes"));
However when I inject IOptions<ThemesOptions>
the Themes
property is null.
An alternative to I changed my extension method to:
public static void AddThemes(this IServiceCollection services, IConfiguration configuration)
services.Configure<ThemesOptions>(configuration.GetSection("Themes"));
Now I can say the following within my application's Startup ConfigureServices
method:
services.AddThemes(Configuration);
This worked fine, however, I feel the problem with this approach is that the extension method only allows the options to be set from the configuration.
I'd appreciate it if someone could confirm whether my first solution is correct and if it can be improved upon.
c# dependency-injection asp.net-core
I have the following extension method to add themes support to my application:
public static void AddThemes(this IServiceCollection services, Action<ThemesOptions> setup)
services.Configure(setup);
Where ThemesOptions
is defined as:
public class ThemesOptions
public IEnumerable<string> Themes get; set;
Now in my application's startup ConfigureServices
method I can say:
services.AddThemes(options =>
options.Themes = Configuration.GetSection("Themes").Get<ThemesOptions>().Themes;
);
I'm not sure that I like that I have to set every property for the options. Alternatively I tried:
services.AddThemes(options =>
options = Configuration.GetSection("Themes").Get<ThemesOptions>();
);
And:
services.AddThemes(options => Configuration.GetSection("Themes"));
However when I inject IOptions<ThemesOptions>
the Themes
property is null.
An alternative to I changed my extension method to:
public static void AddThemes(this IServiceCollection services, IConfiguration configuration)
services.Configure<ThemesOptions>(configuration.GetSection("Themes"));
Now I can say the following within my application's Startup ConfigureServices
method:
services.AddThemes(Configuration);
This worked fine, however, I feel the problem with this approach is that the extension method only allows the options to be set from the configuration.
I'd appreciate it if someone could confirm whether my first solution is correct and if it can be improved upon.
c# dependency-injection asp.net-core
edited Jan 22 at 14:23
Jamalâ¦
30.1k11114225
30.1k11114225
asked Jan 17 at 11:24
nfplee
766
766
add a comment |Â
add a comment |Â
1 Answer
1
active
oldest
votes
up vote
1
down vote
accepted
With your ThemesOptions
defined as:
public class ThemesOptions
public IEnumerable<string> Themes get; set;
and Reference #1 Configure simple options with a delegate
public static void AddThemes(this IServiceCollection services, Action<ThemesOptions> configureOptions)
//Options bound and configured by a delegate
services.Configure<ThemesOptions>(configureOptions);
Will allow the simple delegate to be used when configuring options services.
//Options bound and configured by a delegate
services.AddThemes(option =>
option.Themes = new "Theme1", "Theme2" /*, "SomeOtherTheme" */;
);
Now assuming an app settings json file like
"option1": "value1_from_json",
"option2": -1,
"Themes": [
"Theme1", "Theme2"
]
and Reference #2 Suboptions configuration
you defined the following
public static void AddThemes(this IServiceCollection services, IConfiguration configuration)
// Bind options using a sub-section of the appsettings.json file.
services.Configure<ThemesOptions>(configuration.GetSection("Themes"));
and called like
services.AddThemes(Configuration);
As you rightly stated, it works. Yes. That is because the ThemesOptions
class defines a property Themes
that holds a collection of strings which would match what GetSection("Themes")
would return and thus bind.
Now let's look at the ones that did not work and why they don't
In both cases
services.AddThemes(options =>
options = Configuration.GetSection("Themes").Get<ThemesOptions>();
);
And:
services.AddThemes(options => Configuration.GetSection("Themes"));
you are trying to set the value of a provided argument to the delegate which change the value of the object and in the second one, nothing is done with the option provided. When using the delegate option the value from the settings file are overridden by the configured delegate which is why Themes
property of injected IOptions<ThemesOptions>
is null
services.AddThemes(options =>
options.Themes = Configuration.GetSection("Themes").Get<ThemesOptions>().Themes;
);
works because you are populating the members of the passed parameter which was initialized by the options builder to the delegate.
If this configuration section has a value, that will be used. Otherwise binding by matching property names against configuration keys recursively
Each call to
Configure<TOptions>
adds anIConfigureOptions<TOptions>
service to the service container. When more than one configuration service is enabled, the last configuration source specified wins and sets the configuration value.
Is there no way to set the whole configuration without setting each property individually?
â nfplee
Jan 24 at 21:47
@nfplee clarify what you mean by thewhole configuration
? are you talking about the one classTheme
or all other options in the settings file? .
â Nkosi
Jan 24 at 21:51
I'm using this as an example of a pattern. If in the example above ThemeOptions contained more than one property I'd like to be able to set every property in one line (ideally without using reflection). I had hoped that this was a common scenario.
â nfplee
Jan 25 at 11:57
1
@nfplee if you look at the examples in the links provided you will see that is the convention used by core for options. If themes has multiple properties, the sub options route would populate all the matching properties on the options object
â Nkosi
Jan 25 at 11:59
add a comment |Â
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
1
down vote
accepted
With your ThemesOptions
defined as:
public class ThemesOptions
public IEnumerable<string> Themes get; set;
and Reference #1 Configure simple options with a delegate
public static void AddThemes(this IServiceCollection services, Action<ThemesOptions> configureOptions)
//Options bound and configured by a delegate
services.Configure<ThemesOptions>(configureOptions);
Will allow the simple delegate to be used when configuring options services.
//Options bound and configured by a delegate
services.AddThemes(option =>
option.Themes = new "Theme1", "Theme2" /*, "SomeOtherTheme" */;
);
Now assuming an app settings json file like
"option1": "value1_from_json",
"option2": -1,
"Themes": [
"Theme1", "Theme2"
]
and Reference #2 Suboptions configuration
you defined the following
public static void AddThemes(this IServiceCollection services, IConfiguration configuration)
// Bind options using a sub-section of the appsettings.json file.
services.Configure<ThemesOptions>(configuration.GetSection("Themes"));
and called like
services.AddThemes(Configuration);
As you rightly stated, it works. Yes. That is because the ThemesOptions
class defines a property Themes
that holds a collection of strings which would match what GetSection("Themes")
would return and thus bind.
Now let's look at the ones that did not work and why they don't
In both cases
services.AddThemes(options =>
options = Configuration.GetSection("Themes").Get<ThemesOptions>();
);
And:
services.AddThemes(options => Configuration.GetSection("Themes"));
you are trying to set the value of a provided argument to the delegate which change the value of the object and in the second one, nothing is done with the option provided. When using the delegate option the value from the settings file are overridden by the configured delegate which is why Themes
property of injected IOptions<ThemesOptions>
is null
services.AddThemes(options =>
options.Themes = Configuration.GetSection("Themes").Get<ThemesOptions>().Themes;
);
works because you are populating the members of the passed parameter which was initialized by the options builder to the delegate.
If this configuration section has a value, that will be used. Otherwise binding by matching property names against configuration keys recursively
Each call to
Configure<TOptions>
adds anIConfigureOptions<TOptions>
service to the service container. When more than one configuration service is enabled, the last configuration source specified wins and sets the configuration value.
Is there no way to set the whole configuration without setting each property individually?
â nfplee
Jan 24 at 21:47
@nfplee clarify what you mean by thewhole configuration
? are you talking about the one classTheme
or all other options in the settings file? .
â Nkosi
Jan 24 at 21:51
I'm using this as an example of a pattern. If in the example above ThemeOptions contained more than one property I'd like to be able to set every property in one line (ideally without using reflection). I had hoped that this was a common scenario.
â nfplee
Jan 25 at 11:57
1
@nfplee if you look at the examples in the links provided you will see that is the convention used by core for options. If themes has multiple properties, the sub options route would populate all the matching properties on the options object
â Nkosi
Jan 25 at 11:59
add a comment |Â
up vote
1
down vote
accepted
With your ThemesOptions
defined as:
public class ThemesOptions
public IEnumerable<string> Themes get; set;
and Reference #1 Configure simple options with a delegate
public static void AddThemes(this IServiceCollection services, Action<ThemesOptions> configureOptions)
//Options bound and configured by a delegate
services.Configure<ThemesOptions>(configureOptions);
Will allow the simple delegate to be used when configuring options services.
//Options bound and configured by a delegate
services.AddThemes(option =>
option.Themes = new "Theme1", "Theme2" /*, "SomeOtherTheme" */;
);
Now assuming an app settings json file like
"option1": "value1_from_json",
"option2": -1,
"Themes": [
"Theme1", "Theme2"
]
and Reference #2 Suboptions configuration
you defined the following
public static void AddThemes(this IServiceCollection services, IConfiguration configuration)
// Bind options using a sub-section of the appsettings.json file.
services.Configure<ThemesOptions>(configuration.GetSection("Themes"));
and called like
services.AddThemes(Configuration);
As you rightly stated, it works. Yes. That is because the ThemesOptions
class defines a property Themes
that holds a collection of strings which would match what GetSection("Themes")
would return and thus bind.
Now let's look at the ones that did not work and why they don't
In both cases
services.AddThemes(options =>
options = Configuration.GetSection("Themes").Get<ThemesOptions>();
);
And:
services.AddThemes(options => Configuration.GetSection("Themes"));
you are trying to set the value of a provided argument to the delegate which change the value of the object and in the second one, nothing is done with the option provided. When using the delegate option the value from the settings file are overridden by the configured delegate which is why Themes
property of injected IOptions<ThemesOptions>
is null
services.AddThemes(options =>
options.Themes = Configuration.GetSection("Themes").Get<ThemesOptions>().Themes;
);
works because you are populating the members of the passed parameter which was initialized by the options builder to the delegate.
If this configuration section has a value, that will be used. Otherwise binding by matching property names against configuration keys recursively
Each call to
Configure<TOptions>
adds anIConfigureOptions<TOptions>
service to the service container. When more than one configuration service is enabled, the last configuration source specified wins and sets the configuration value.
Is there no way to set the whole configuration without setting each property individually?
â nfplee
Jan 24 at 21:47
@nfplee clarify what you mean by thewhole configuration
? are you talking about the one classTheme
or all other options in the settings file? .
â Nkosi
Jan 24 at 21:51
I'm using this as an example of a pattern. If in the example above ThemeOptions contained more than one property I'd like to be able to set every property in one line (ideally without using reflection). I had hoped that this was a common scenario.
â nfplee
Jan 25 at 11:57
1
@nfplee if you look at the examples in the links provided you will see that is the convention used by core for options. If themes has multiple properties, the sub options route would populate all the matching properties on the options object
â Nkosi
Jan 25 at 11:59
add a comment |Â
up vote
1
down vote
accepted
up vote
1
down vote
accepted
With your ThemesOptions
defined as:
public class ThemesOptions
public IEnumerable<string> Themes get; set;
and Reference #1 Configure simple options with a delegate
public static void AddThemes(this IServiceCollection services, Action<ThemesOptions> configureOptions)
//Options bound and configured by a delegate
services.Configure<ThemesOptions>(configureOptions);
Will allow the simple delegate to be used when configuring options services.
//Options bound and configured by a delegate
services.AddThemes(option =>
option.Themes = new "Theme1", "Theme2" /*, "SomeOtherTheme" */;
);
Now assuming an app settings json file like
"option1": "value1_from_json",
"option2": -1,
"Themes": [
"Theme1", "Theme2"
]
and Reference #2 Suboptions configuration
you defined the following
public static void AddThemes(this IServiceCollection services, IConfiguration configuration)
// Bind options using a sub-section of the appsettings.json file.
services.Configure<ThemesOptions>(configuration.GetSection("Themes"));
and called like
services.AddThemes(Configuration);
As you rightly stated, it works. Yes. That is because the ThemesOptions
class defines a property Themes
that holds a collection of strings which would match what GetSection("Themes")
would return and thus bind.
Now let's look at the ones that did not work and why they don't
In both cases
services.AddThemes(options =>
options = Configuration.GetSection("Themes").Get<ThemesOptions>();
);
And:
services.AddThemes(options => Configuration.GetSection("Themes"));
you are trying to set the value of a provided argument to the delegate which change the value of the object and in the second one, nothing is done with the option provided. When using the delegate option the value from the settings file are overridden by the configured delegate which is why Themes
property of injected IOptions<ThemesOptions>
is null
services.AddThemes(options =>
options.Themes = Configuration.GetSection("Themes").Get<ThemesOptions>().Themes;
);
works because you are populating the members of the passed parameter which was initialized by the options builder to the delegate.
If this configuration section has a value, that will be used. Otherwise binding by matching property names against configuration keys recursively
Each call to
Configure<TOptions>
adds anIConfigureOptions<TOptions>
service to the service container. When more than one configuration service is enabled, the last configuration source specified wins and sets the configuration value.
With your ThemesOptions
defined as:
public class ThemesOptions
public IEnumerable<string> Themes get; set;
and Reference #1 Configure simple options with a delegate
public static void AddThemes(this IServiceCollection services, Action<ThemesOptions> configureOptions)
//Options bound and configured by a delegate
services.Configure<ThemesOptions>(configureOptions);
Will allow the simple delegate to be used when configuring options services.
//Options bound and configured by a delegate
services.AddThemes(option =>
option.Themes = new "Theme1", "Theme2" /*, "SomeOtherTheme" */;
);
Now assuming an app settings json file like
"option1": "value1_from_json",
"option2": -1,
"Themes": [
"Theme1", "Theme2"
]
and Reference #2 Suboptions configuration
you defined the following
public static void AddThemes(this IServiceCollection services, IConfiguration configuration)
// Bind options using a sub-section of the appsettings.json file.
services.Configure<ThemesOptions>(configuration.GetSection("Themes"));
and called like
services.AddThemes(Configuration);
As you rightly stated, it works. Yes. That is because the ThemesOptions
class defines a property Themes
that holds a collection of strings which would match what GetSection("Themes")
would return and thus bind.
Now let's look at the ones that did not work and why they don't
In both cases
services.AddThemes(options =>
options = Configuration.GetSection("Themes").Get<ThemesOptions>();
);
And:
services.AddThemes(options => Configuration.GetSection("Themes"));
you are trying to set the value of a provided argument to the delegate which change the value of the object and in the second one, nothing is done with the option provided. When using the delegate option the value from the settings file are overridden by the configured delegate which is why Themes
property of injected IOptions<ThemesOptions>
is null
services.AddThemes(options =>
options.Themes = Configuration.GetSection("Themes").Get<ThemesOptions>().Themes;
);
works because you are populating the members of the passed parameter which was initialized by the options builder to the delegate.
If this configuration section has a value, that will be used. Otherwise binding by matching property names against configuration keys recursively
Each call to
Configure<TOptions>
adds anIConfigureOptions<TOptions>
service to the service container. When more than one configuration service is enabled, the last configuration source specified wins and sets the configuration value.
answered Jan 22 at 23:53
Nkosi
1,870619
1,870619
Is there no way to set the whole configuration without setting each property individually?
â nfplee
Jan 24 at 21:47
@nfplee clarify what you mean by thewhole configuration
? are you talking about the one classTheme
or all other options in the settings file? .
â Nkosi
Jan 24 at 21:51
I'm using this as an example of a pattern. If in the example above ThemeOptions contained more than one property I'd like to be able to set every property in one line (ideally without using reflection). I had hoped that this was a common scenario.
â nfplee
Jan 25 at 11:57
1
@nfplee if you look at the examples in the links provided you will see that is the convention used by core for options. If themes has multiple properties, the sub options route would populate all the matching properties on the options object
â Nkosi
Jan 25 at 11:59
add a comment |Â
Is there no way to set the whole configuration without setting each property individually?
â nfplee
Jan 24 at 21:47
@nfplee clarify what you mean by thewhole configuration
? are you talking about the one classTheme
or all other options in the settings file? .
â Nkosi
Jan 24 at 21:51
I'm using this as an example of a pattern. If in the example above ThemeOptions contained more than one property I'd like to be able to set every property in one line (ideally without using reflection). I had hoped that this was a common scenario.
â nfplee
Jan 25 at 11:57
1
@nfplee if you look at the examples in the links provided you will see that is the convention used by core for options. If themes has multiple properties, the sub options route would populate all the matching properties on the options object
â Nkosi
Jan 25 at 11:59
Is there no way to set the whole configuration without setting each property individually?
â nfplee
Jan 24 at 21:47
Is there no way to set the whole configuration without setting each property individually?
â nfplee
Jan 24 at 21:47
@nfplee clarify what you mean by the
whole configuration
? are you talking about the one class Theme
or all other options in the settings file? .â Nkosi
Jan 24 at 21:51
@nfplee clarify what you mean by the
whole configuration
? are you talking about the one class Theme
or all other options in the settings file? .â Nkosi
Jan 24 at 21:51
I'm using this as an example of a pattern. If in the example above ThemeOptions contained more than one property I'd like to be able to set every property in one line (ideally without using reflection). I had hoped that this was a common scenario.
â nfplee
Jan 25 at 11:57
I'm using this as an example of a pattern. If in the example above ThemeOptions contained more than one property I'd like to be able to set every property in one line (ideally without using reflection). I had hoped that this was a common scenario.
â nfplee
Jan 25 at 11:57
1
1
@nfplee if you look at the examples in the links provided you will see that is the convention used by core for options. If themes has multiple properties, the sub options route would populate all the matching properties on the options object
â Nkosi
Jan 25 at 11:59
@nfplee if you look at the examples in the links provided you will see that is the convention used by core for options. If themes has multiple properties, the sub options route would populate all the matching properties on the options object
â Nkosi
Jan 25 at 11:59
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f185297%2fadding-extension-methods-to-iservicecollection-in-asp-net-core%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password