-
Notifications
You must be signed in to change notification settings - Fork 69
Semi-Automatic options configuration improvements #224
Comments
This is somewhat related to #222 Assuming we had something like a public class SetupOptions : IConfigureOptions<MvcOptions>, IConfigureOptions<RazorViewEngineOptions>, IConfigureOptions<LocalizationOptions> {
public SetupOptions(IStringLocalizer<Model> localizer)
public void ConfigureOptions(LocalizationOptions options)
{
options.ResourcesPath = "Resources";
}
public void ConfigureOptions(MvcOptions options)
{
options.ModelBindingMessageProvider.ValueMustNotBeNullAccessor =
value => localizer["Value '{0}' appears to be null and that's not valid.", value];
}
public void ConfigureOptions(RazorViewEngineOptions options)
{
var embeddedProvider = new EmbeddedFileProvider(typeof(Model).GetTypeInfo().Assembly);
options.FileProviders.Add(embeddedProvider);
}
} |
As mentioned in the description, there be 🐉s here.
That'll work though it seems odd to separate configuration from |
BTW it's not clear any user |
I like decoupling this feature from startup. It solves a bunch of problems. |
That's fine -- I just said it was "odd" (timing) 😸 But, will we require a separate class when performing service-reliant configuration? |
I don't think its too bad to have an optional dedicated ConfigureOptions class that configures a whole bunch of options. public class ConfigureOptions : IConfigureOptions<SomeOptions>, IPostConfigureOptions<OtherOptions>, IConfigureNamedOptions<NamedOptions> {
public ConfigureOptions(IServiceA a, IServiceB b) { }
public Configure(SomeOptions o) { o.Value = a.DoSomething() }
public PostConfigure(OtherOptions o) { o.Value = b.DoSomething(); }
public Configure(NamedOptions o, string name) {
if (name == b.ShouldConfigure(name))
o.Value = b.DoSomething());
} Its not required, as you can still do the old I'm not exactly sure where the best place to plumb all of this, maybe a new line in Program.cs? public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
// This would just translate to a services.RegisterOptionsSetup<ConfigureOptions>
.ConfigureOptions<ConfigureOptions>()
.Build(); |
|
From @dougbu @davidfowl
A couple of months back, Fowler and I discussed ways to make it easier to configure options. My main concern at that time was the machinations necessary to set options based on other services – the whole
IConfigureOptions<TOptions>
rigmarole feels at best second class. We’re hoping you can find a germ in this worth adding sooner or later. That is, please run with something.I wrote up the https://gist.github.com/dougbu/bc4880f0aadce9d94b7df91d53782da0 gist based on these discussions. The basic thing is semi-automatic discovery of
Startup
methods that configure options. These methods are all namedConfigureOptions
, take a first parameter of theTOptions
they set, and may have additional parameters grabbed from DI.David and I covered a few questions but didn’t completely resolve them:
ConfigureOptions
methods always be found and executed? Or, must the user callservices.Configure<TOptions>()
for everyTOptions
or perhaps a less-granularservices.ConfigureOptions()
?ConfigureOptions
methods be withinStartup
? For example, the explicit configuration request might beservices.ConfigureOptions(this)
if you do want to use theStartup
class.ConfigureOptions
methods executed and in what relative order? Granularservices.Configure<TOptions>()
methods might be semantically identical to placing anIConfigureOptions<TOptions>
implementation into DI at that time. If supported, we’d need to decide ifservices.ConfigureOptions()
called the methods in whatever order Reflection returns, alphabetically byTOptions
name, or something else. And ifUseStartup<Startup>
impliesConfigureOptions()
discovery, are the methods executed before or afterIConfigureOptions<TOptions>
implementations thatConfigureServices()
adds?About all we resolved is that what we have now isn’t great and
Startup: IConfigureOptions<MvcOptions>, IConfigureOptions<RazorViewEngineOptions>
wouldn’t help with service resolution (besides being butt-ugly).The text was updated successfully, but these errors were encountered: