![](/img/trans.png)
[英]Single object instance using IServiceCollection.AddSingleton()
[英]What are the practical scenarios to use IServiceCollection.AddTransient, IServiceCollection.AddSingleton and IServiceCollectionAddScoped Methods?
閱讀這篇文章后,我可以理解AddTransient
、 AddScoped
和AddSingleton
之間的AddTransient
,但是,我無法看到它們各自的實際用法。
我的理解是
添加瞬態
每次客戶端請求時創建一個新實例。
services.AddTransient<IDataAccess, DataAccess>();
每次客戶端代碼請求它時都會返回一個新的 DataAccess 對象。 更可能是構造函數。
AddTransient 的使用
在我們必須訪問數據庫以讀取和更新它並銷毀訪問對象 (DataAccess) 的情況下,最好使用AddTransient
- 不確定線程是否安全。
添加范圍
為每個 http Web 請求創建一個新實例。
AddScoped 的使用
services.AddScoped<ShoppingCart>(serviceProvider => ShoppingCart.GetShoppingCart(serviceProvider));
這意味着每個 Web 請求都將擁有自己的購物車實例,這意味着每個用戶/客戶將擁有自己的用於該 http Web 請求的購物車實例。
添加單例
為所有 http Web 請求創建單個實例。
AddSingleton 的使用
在示例應用程序中找到此代碼,但我不明白它是如何有用的。
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
有人可以在何時使用 AddSingleton 並檢查我對 AddTransient 和 AddScoped 的理解是否正確?
您對所有 3 個范圍的理解是正確的。
當組件無法共享時,將使用瞬態。 一個非線程安全的數據庫訪問對象就是一個例子。
Scoped可用於實體框架數據庫上下文。 主要原因是從數據庫中獲取的實體將附加到請求中所有組件看到的相同上下文。 當然,如果您打算並行使用它進行查詢,則不能使用 Scoped。
Scoped 對象的另一個示例是某種RequestContext
類,其中包含例如調用者的用戶名。 中間件/MVC 過濾器可以請求它並填寫信息,其他組件也可以請求它,它肯定會包含當前請求的信息。
單例組件總是共享的,因此它們最適合不需要綁定到請求的線程安全組件。 一個例子是IOptions
,它可以訪問配置設置。 在單個靜態HttpClient
實例上使用SendAsync
的HttpClient
包裝類也將是完全線程安全的,並且非常適合作為單例。
請注意,如果您有一個依賴於 Scoped 組件的 Singleton 組件,它的依賴項將在它之前被釋放。 因此,一個組件不能依賴於比其自身范圍更小的另一個組件。
我已經看到了“只使用AddTransient<T>()
”的觀點,但我不同意。
我討厭在不需要的時候分配東西,所以如果我知道我正在創建線程安全的東西,或者我有明確的文檔表明有一個單例實例是預期的用法,那么我正在創建一個單例。
這是作為單例的 ApplicationInsights TelemetryClient 實例。 他們的文檔說這是有效的。
telemetryClient = new TelemetryClient(TelemetryConfiguration.Active);
services.AddSingleton<TelemetryClient>(telemetryClient);
在這個項目中,我也使用 Azure 表存儲,我發現創建一個 CloudTableClient 作為單例工作得很好。 我不需要為每個請求不斷創建它的實例。
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(Configuration.GetValue<string>("storageAccountConnectionString"));
CloudTableClient someTableClient = storageAccount.CreateCloudTableClient();
services.AddSingleton<CloudTableClient>(someTableClient);
從某種意義上說,它相當於一個類的只讀靜態屬性,例如:
public static readonly CloudTableClient cloudTableClient = new CloudTableClient(...);
...在整個應用程序中只有一個實例,但是通過使用services.AddSingleton<T>()
我們可以使用依賴注入直接訪問它。
對我來說AddScoped<T>()
一個例子是,我想將獲取 Application Insights 所需的 JavaScript 嵌入到網頁中,但我使用了Content-Security-Policy ,所以我需要在任何-頁面 JavaScript。 我有一些代碼可以幫助我做到這一點。
services.AddScoped<ApplicationInsightsJsHelper>();
我還沒有發現需要將AddTransient<T>()
用於任何事情。 可能是我不認為我必須創建的東西,每次我需要它們時,作為“服務”......它們只是我新添加的變量。 從某種意義上說, AddTransient<T>()
是工廠模式的隱藏用途......而不是調用靜態MyServiceFactory.Create()
函數,您可以使用依賴注入(有效地)為您做同樣的事情。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.