.NET Core Singleton Creation is called multiple times

前端 未结 2 2096
清歌不尽
清歌不尽 2021-02-19 15:34

I\'m registering a service as a singleton in .NET Core. Yet I\'m seeing the constructor for the singleton called multiple times.

services.AddSingleton

        
相关标签:
2条回答
  • 2021-02-19 15:49

    Does building the provider create a new container so all of the services get reregistered?

    Yes. See the source code.

    If so, How can I call a method to register my dynamic validators in the singleton container with the existing IServiceProvider, is there a way to invoke some registration once after the servicecontainer is built?

    I'm not really understanding why this is a problem. You should be registering all of your services one time at application startup in the Composition Root.

    The DI container is then responsible for resolving the object graphs of the application. The application itself shouldn't have a dependency on it, nor be required to update it.

    You should be injecting DbAuthorizationOptions in the place where you need to use it.

    public class Foo : IFoo
    {
        private readonly DbAuthorizationOptions authOptions;
    
        public Foo(DbAuthorizationOptions authOptions) // <-- Inject parameters
        {
            this.authOptions = authOptions ??
                throw new ArgumentNullException(nameof(authOptions));
        }
    
        public void DoSomething()
        {
            // TODO: Inject the type that has the BuildDynamicValidatorFactory
            // method and the serviceOption (whatever type that is) here
            // either as a method parameter of this method, or a constructor
            // parameter of this class.
            var validator = BuildDynamicValidatorFactory(serviceOption).Invoke(provider, null);
            // Now we have an instance of authOptions that can be used
            authOptions.ValidatorOptions.AddValidatorForSet(validator);
        }
    }
    

    Note that the DI container automatically provides the DbAuthorizationOptions if injected into another type that is also resolved through DI (such as a controller or filter).

    NOTE: It isn't very clear from your question where you need to do this. You mention that you want it to happen once, which usually means to put it at application startup. But users cannot interact with code that runs at startup. So, maybe you could use a filter. It really all depends on where in the lifecycle of the application it has to happen.

    0 讨论(0)
  • 2021-02-19 15:55

    You can declare a dependency on IServiceProvider -- don't build it, inject it.

    public class SomeController
    {
        DbAuthorizationOptions authOptions;
        public SomeController(IServiceProvider provider)
        {
            authOptions = provider.GetSerivce<DbAuthorizationOptions>();
        }
    }
    

    But this is the service locator anti-pattern. As I commented on NightOwl888's post after you gave more details, a factory is probably a better approach.

    0 讨论(0)
提交回复
热议问题