C
C#2y ago
Anton

❔ API DI advice

I want to implement a configurable injected class via an extension method, using the options system for the configuration. By looking through some code, I gathered that by doing .Configure<Options> you can chain configuration actions, which will execute when the container is being built. When the service that requires these options is instantiated, it would get the options snapshot from the service provider as a service. However, what do I do if I still want to use this system, chaining the repeated actions, but I also want to register more services from these actions? How do I reference the service collection? Do I keep a reference to it in the options class? That's not it, right? Basically, I need to register a few dependencies while the service is being configured from those actions. Also, I've seen a library use ServiceDescriptor added explicitly, but the code there is really funky, I don't understand how it works (it being encumbered with abstractions does not help).
10 Replies
Stroniax
Stroniax2y ago
You shouldn't need to chain configuration actions for the same configuration object - do all your configuration in one call.
.Configure<JsonSerializerOptions>(options => {
options.WriteIndented = true;
options.IgnoreCase = true;
})
.AddSingleton<ISomething, Something>() // and so on
.Configure<JsonSerializerOptions>(options => {
options.WriteIndented = true;
options.IgnoreCase = true;
})
.AddSingleton<ISomething, Something>() // and so on
Otherwise, what are you trying to do?
Anton
Anton2y ago
I want to add more services as part of configuration like by calling options.Add(something) it would both modify some data on the options class and add a service to the service collection I don't understand how I should design it to allow that I want to use the options system just because I figured it's a standard practice
Stroniax
Stroniax2y ago
I think you need to use an extension method and retain the services:
public static class MyStartupExtensions {
public static IServiceCollection AddMyService(this IServiceCollection services) {
return services.AddSingleton<IMyService, MyService>()
.Configure<MyOptions>(_ => {});
}

// in Startup
services.AddMyService()
.Configure<MyOptions>(_ => {})
public static class MyStartupExtensions {
public static IServiceCollection AddMyService(this IServiceCollection services) {
return services.AddSingleton<IMyService, MyService>()
.Configure<MyOptions>(_ => {});
}

// in Startup
services.AddMyService()
.Configure<MyOptions>(_ => {})
Anton
Anton2y ago
configuting something from multiple places is convenient
Stroniax
Stroniax2y ago
This lets you add the service and it's base components in one call, and then configure them more later if you so desire.
Anton
Anton2y ago
I don't think you quite get what I mean $code
MODiX
MODiX2y ago
To post C# code type the following: ```cs // code here ``` Get an example by typing $codegif in chat If your code is too long, post it to: https://paste.mod.gg/
Anton
Anton2y ago
BlazeBin - exlipmndcjqv
A tool for sharing your source code with the world!
Anton
Anton2y ago
The problem is that when I call configuration.Add, I also need it to add the type it gets as a scoped service into the service collection I want it to look like this
builder.Services.AddKeyed<IServiceBaseType>(o =>
{
o.Add<TypeA>("KeyA");
o.Add<TypeB>("KeyB");
});

// later

// either ConfigureKeyed or AddKeyed again, configuring the same thing
builder.Services.AddKeyed<IServiceBaseType>(o =>
{
o.Add<TypeC>("KeyC");
});
builder.Services.AddKeyed<IServiceBaseType>(o =>
{
o.Add<TypeA>("KeyA");
o.Add<TypeB>("KeyB");
});

// later

// either ConfigureKeyed or AddKeyed again, configuring the same thing
builder.Services.AddKeyed<IServiceBaseType>(o =>
{
o.Add<TypeC>("KeyC");
});
I don't understand what's the convention for this What such configuration should even look like Like I guess I could just do builder.Services.AddKeyed<BaseType, Type>("key") multiple times, but then how do I implement the configuration here? Do I add the type to the services collection immediately, and then configure separately by adding the delegate via .Configure? Or do I build up a configuration object by the result of the call to the action I get as a parameter, and then add a .Configure with a member method, while adding the types as I'm configuring it. But then the configuration would effectively run instantly, while with .Configure it doesn't, right? I now realize I'm quite confused about this .Configure thing It just gets you a reference to the same options object in a passed action, but like what's the point if I would be adding types instantly? It just doesn't make sense Like what's the conventional way of doing this, I'm asking again. All the ways I can think of feel like hacks Is there a way to make the aspnet core builder make a callback to a method before resolving the container and making the application object? otherwise the thing I'm trying to do would get quite ugly and would make way more objects than needed
Accord
Accord2y ago
Was this issue resolved? If so, run /close - otherwise I will mark this as stale and this post will be archived until there is new activity.