-
Notifications
You must be signed in to change notification settings - Fork 67
Add Initialize<TOptions> #187
Conversation
For me it looks like the same as What if something will require step number 3 ( Maybe need to create more complex solution? I know that's too much, but more long-term solution. |
|
||
/// <summary> | ||
/// Initializes a new instance with the specified options configurations. | ||
/// </summary> | ||
/// <param name="setups">The configuration actions to run.</param> | ||
public OptionsFactory(IEnumerable<IConfigureOptions<TOptions>> setups) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we keep the old ctor for compat, and have it chain to the new ctor? DI would only call the new ctor anyway, but it would avoid a breaking change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We added this type in 2.0 so no breaking change thankfully
@@ -69,5 +69,43 @@ public static IServiceCollection Configure<TOptions>(this IServiceCollection ser | |||
|
|||
public static IServiceCollection ConfigureAll<TOptions>(this IServiceCollection services, Action<TOptions> configureOptions) where TOptions : class | |||
=> services.Configure(name: null, configureOptions: configureOptions); | |||
|
|||
/// <summary> | |||
/// Registers an action used to Initialize a particular type of options. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't need to capitalize the I
of Initialize
(it's just a word here, not a method name).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(Applies to other doc comments in this PR.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah I'll fix, global find/replace fail, I just cloned the ConfigureOptions files and replaced
/// <param name="name">The name of the options instance.</param> | ||
/// <param name="InitializeOptions">The action used to Initialize the options.</param> | ||
/// <returns>The <see cref="IServiceCollection"/> so that additional calls can be chained.</returns> | ||
public static IServiceCollection Initialize<TOptions>(this IServiceCollection services, string name, Action<TOptions> InitializeOptions) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rename InitializeOptions
param to start with lowercase letter.
public class InitializeOptions<TOptions> : IInitializeOptions<TOptions> where TOptions : class | ||
{ | ||
/// <summary> | ||
/// Constructor. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Creates a new instance of...
/// <param name="action">The action to register.</param> | ||
public InitializeOptions(string name, Action<TOptions> action) | ||
{ | ||
Name = name; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do these params need any checks? Can they be empty? Null? Anything?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
null name signify's applying to all names.
string.empty is used to target the 'default' name, i.e. the overloads that don't specify name
Passing in a null action is equivalent to passing in a no-op o => { }, so I don't think its something we explicitly need to block (we didn't for the existing https://github.com/aspnet/Options/blob/dev/src/Microsoft.Extensions.Options/ConfigureOptions.cs, so we need to be consistent) Note: we do require non null actions on the sugar Configure/Initialize
apis since it doesn't make sense to add no-op/null actions there.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok.
namespace Microsoft.Extensions.Options | ||
{ | ||
/// <summary> | ||
/// Implementation of IInitializeNamedOptions. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can use a typeref for the type in this doc.
services.Configure<FakeOptions>(o => o.Message += "0"); | ||
services.Configure<FakeOptions>("1", o => o.Message += "1"); | ||
services.InitializeAll<FakeOptions>(o => o.Message += "Initialize"); | ||
services.Initialize<FakeOptions>(o => o.Message += "2"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I'm just confused, but doesn't this Initialize
initialize all FakeOptions, because no name was specified??
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah its a bit confusing,
All overloads that don't take a name target the Options.DefaultName = string.Empty; This was done to make all of the existing options.Configures behave the same in Options 2.0 since we added names, and wanted to preserve the existing semantics and behaviors.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should define some non-empty string to have this meaning. Like "Default", or something more specific if we think avoiding collisions is important. The empty-string is very un-documenting.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah let's get that figured out.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, the actual value for the default name doesn't matter too much, we use Options.DefaultName everywhere, its currently set to string.empty since that seemed like a good default to me, in general the constant should be used everywhere but if we want to change it, its just changing this line: https://github.com/aspnet/Options/blob/dev/src/Microsoft.Extensions.Options/Options.cs#L11
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To clarify, whatever value we pick, its just used as the default for the overloads that don't specify a name, so it doesn't really have any documention value other than if you were debugging a custom IConfigure/InitializeOptions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think its pretty clear today if you look at the usage in the overloads with the constant:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't have a strong opinion on the exact name, I just feel strongly about "let's get that figured out" 😄 @ajcvickers ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't feel strongly, so I'll let @HaoK make the call. I would be a little confused if I was attempting to debug code that was using this, or if I passed empty string and go back something, but I guess most people won't do those things.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay lets keep it as empty string for now, since this isn't new for Initialize.
empty string is pretty weird name to pick, and you wouldn't actually see any issues with using it as your name, unless you configured using both methods.
services.Configure(o => o.Foo = "bar");
services.Configure("", o => o.Foo = "what??");
Updated to fix casing, also added references in the doc comments for Configure/Initialize to each other and whether they run before/after each other. Also added a test/fix for a minor issue with old IConfigureOptions being run for all named instances instead of only the default instance |
Merged 52ab5f1 |
#185
Needed to replace double locking/options fixup in auth as we discussed last week.
@ajcvickers @Tratcher @Eilon @davidfowl