C
C#2y ago
Anton

❔ Resolve a service before the container is built

Is it possible? My use case is that I want to share an object when I'm configuring the services. This question is ungooglable in the way I describe it
33 Replies
Auros
Auros2y ago
If I'm reading this correctly, you want to resolve a service, and then use that service to further configure your services? Can you prove a code example of what you would like to do? (It doesn't have to work)
Anton
AntonOP2y ago
I just did kind of a hack of what I need. But I'm sure there's a better way. https://github.com/AntonC9018/49/blob/auth/source/fourtynine/Utils/KeyedProvider.cs and usage: https://github.com/AntonC9018/49/blob/auth/source/fourtynine/Program.cs#L146-L152 imagine doing this configuration at multiple points in some configuration classes that can't share context directly.
GitHub
49/KeyedProvider.cs at auth · AntonC9018/49
Contribute to AntonC9018/49 development by creating an account on GitHub.
GitHub
49/Program.cs at auth · AntonC9018/49
Contribute to AntonC9018/49 development by creating an account on GitHub.
Anton
AntonOP2y ago
@Auros not necessarily a service, some piece of state in this case would suffice
Auros
Auros2y ago
I might be wrong with what you're trying to do, but if the shared object doesn't require a dependency from the built container, you can use the builder.Host.Properties dictionary to store shared objects during the host building process.
Anton
AntonOP2y ago
gotcha are there events that trigger before the container gets built? do you know by any chance?
Auros
Auros2y ago
Not that I know of. If you need to set the shared object, do it after you call WebApplication.CreateBuilder. Technically a lambda provided to ctx.Host.ConfigureServices is called while the container is building, but that's not really an ideal event.
Anton
AntonOP2y ago
it's fine, I can just build that object with the dictionary dynamically, setting it both as a singleton in the DI and on those properties. thanks for the insight
Omnissiah
Omnissiah2y ago
could you just call a surrogate object that initialize the real object for you? or use a hosted service?
Anton
AntonOP2y ago
I don't know what either of these are
mikernet
mikernet2y ago
Tbh not entirely sure what you are trying to eliminate or "fix" here What is the part that doesnt work how you want it to and how do you want it to work
Anton
AntonOP2y ago
hosted service can serve as a callback don't know what you mean by surrogate object getting a reference to the same configuration object before the app is built I managed to do this with properties
Anton
AntonOP2y ago
Anton
AntonOP2y ago
tho not sure what key to use, I haven't checked what FullName returns also been asking what's the convention
mikernet
mikernet2y ago
This seems like an odd way to do this tbh. I would just register each IUserEmailConfirmationProvider, give that interface a Name or Scheme property, then have the KeyedProvider ctor take an IEnumerable<IUserEmailConfirmationProvider> which it then uses to build its dictionary using the Name/Scheme as the key
Anton
AntonOP2y ago
that won't work, because you'd need to have an instance to get the scheme nane in the first place but it could be scoped or whatever
mikernet
mikernet2y ago
You don't need an instance, those instances get passed into the key provider when it is first requested from the container, i.e when the container builds the key provider
Anton
AntonOP2y ago
with abstract statics or with some weird reflection maybe
mikernet
mikernet2y ago
It will inject the instances As an IEnumerable<>
Anton
AntonOP2y ago
so all would get instantiated every time I need one?
mikernet
mikernet2y ago
It's a singleton, so no
Anton
AntonOP2y ago
the email provider may not be a singleton
mikernet
mikernet2y ago
Hmm I see, give me a sec
Anton
AntonOP2y ago
your idea could work if you were to also make email provider factories, but that's a ridiculous amount of extra boilerplate needed or like descriptors
mikernet
mikernet2y ago
In KeyedProviderExtensions.AddKeyed you can register this singleton which gets the actual instance:
class KeyedInstanceProvider<TBaseType>
{
public KeyedInstanceProvider(string schemaName, IServiceProvider serviceProvider)
{
}

public TBaseType? Get() { ... }
}
class KeyedInstanceProvider<TBaseType>
{
public KeyedInstanceProvider(string schemaName, IServiceProvider serviceProvider)
{
}

public TBaseType? Get() { ... }
}
Then KeyedProvider ctor takes IEnumerable<KeyedInstanceProvider<TBaseType>> as the parameter
Anton
AntonOP2y ago
+ extra anstraction so that would be the conventional way of doing it right?
mikernet
mikernet2y ago
That's the "proper" way I would do it using .net DI
Anton
AntonOP2y ago
ok thanks
mikernet
mikernet2y ago
Then you can do away with the shared configuration object Also I dont think the return needs to be nullable BaseType AFAICT. If there's a mapping for it then it will return an instance, otherwise it will throw.
Anton
AntonOP2y ago
you mean in your code?
mikernet
mikernet2y ago
In yours as well But yes https://github.com/AntonC9018/49/blob/auth/source/fourtynine/Utils/KeyedProvider.cs#L97 I dont see that ever returning null
Anton
AntonOP2y ago
yeah it shouldn't throw there
mikernet
mikernet2y ago
Gotcha 🙂
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.
Want results from more Discord servers?
Add your server