簡體   English   中英

.NET Core單例創建被多次調用

[英].NET Core Singleton Creation is called multiple times

我在.NET Core中將服務注冊為單例。 但是我看到單例的構造函數被多次調用。

services.AddSingleton<DbAuthorizationOptions, ContextAuthorizationOptions>();

我的上下文授權選項只是將實體類型字典發送給IValidators ,上下文授權選項被傳遞到DBContext ,以自動運行驗證。

在注冊服務期間,我還將動態驗證器與在DI中注冊的容器一起注冊。

var useDynamicValidator = serviceOption.ValidatorOptions != null;
if(useDynamicValidator)
{
    //TODO: Extract this to before the register service no sense in building the provider each time
    //TODO: Make this cleaner don't be dependent on Authorization options
    var provider = services.BuildServiceProvider();
    var authOptions = provider.GetService<DbAuthorizationOptions>();
    var validator = BuildDynamicValidatorFactory(serviceOption).Invoke(provider, null);
    authOptions.ValidatorOptions.AddValidatorForSet(validator);
}

我注意到,當我在提供程序上調用GetService時,會收到一個新的單例,而不是現有的單例。 構建提供者是否會創建一個新的容器,以便重新注冊所有服務?

如果是這樣,我該如何調用一種方法來在現有IServiceProvider的單例容器中注冊我的動態驗證器,是否可以在構建服務容器后立即調用一些注冊?

構建提供者是否會創建一個新容器,以便重新注冊所有服務?

是。 參見源代碼

如果是這樣,我該如何調用一種方法來向現有IServiceProvider在單例容器中注冊我的動態驗證器,是否可以在構建servicecontainer之后調用一次注冊?

我不是很了解為什么這是一個問題。 您應該在應用程序啟動時一次Composition Root中注冊所有服務。

然后,DI容器負責解析應用程序的對象圖 應用程序本身不應該依賴它,也不需要更新它。

您應該在需要使用DbAuthorizationOptions的地方注入它。

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);
    }
}

請注意,如果將DI容器注入也通過DI解析的另一種類型(例如,控制器或過濾器),則DI容器會自動提供DbAuthorizationOptions

注意:從您的問題尚不清楚,您需要在哪里執行此操作。 您提到您希望它發生一次,這通常意味着將其放在應用程序啟動時。 但是用戶無法與啟動時運行的代碼進行交互。 因此,也許您可​​以使用filter 這一切都是在那里它發生在應用程序的生命周期取決於。

您可以聲明對IServiceProvider的依賴關系-不要構建它,注入它。

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

但這是服務定位器的反模式。 在您提供了更多詳細信息之后,我對NightOwl888的帖子發表了評論時,工廠可能是一個更好的方法。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM