-
Notifications
You must be signed in to change notification settings - Fork 25
Description
Requirements
I tried to use the new (experimental) dependency injection from 2.1.0 to set up OpenFeature but I found it hard to do this with no access to the service provider from the provider factory.
This causes issues with lifetimes and dependencies.
For example, if you have a client library that is registered as a singleton then you can't re-use that instance from the OpenFeature dependency injection builder. You might want to keep the original client available because it has features that OpenFeature does not have yet, like tracking, but only register a singleton with dependency injection because it keeps a connection to the server and a local cache. You might also want that client cleaned up when the service provider is cleaned up, which doesn't happen if you make it in the factory. If the client library needs access to other services, like an ILogger, you can't access them from the feature provider factory to create the client.
The feature builder has an IServiceCollection but you shouldn't build ephemeral service providers because the lifetime of the services are tied to the lifetime of the service provider, and it can also cause problems with the ordering of the service registrations because it only has access to what is registered at that point.
Just registering a FeatureProvider outside the builder almost works, but fails because HasDefaultProvider is not set, and then it falls back to named but throws because the names are empty (fails because .First() throws on an empty collection)
One solution could be to add an overload of AddOpenFeature that provides access to the IServiceProvider in the callback.
Another possible solution is to change AddProvider<T> to the type of the provider instead of using provider factories, and just register the provider type and let the dependency injection resolve it, so that it can just be given anything it needs in its constructor through normal constructor injection. Basically AddProvider<T> just becomes a convenience method over AddTransient<T> that also sets HasDefaultProvider or something like that, with similar for named/keyed.
Another option is to just let it use whatever is already registered outside the builder.
If I'm just misunderstanding how it should be done then let me know.
cc @arttonoyan