在 ASP.NET Core 中,有三種型別的依賴註入服務。您可以在此處詳細閱讀它們。在這篇文章中,我們將重點介紹如何在單例服務中使用作用域內服務。
在單例服務中使用作用域服務的主要目標是存取單例服務中不可用的特定於請求的數據或資源。例如,您可能希望從單一例項服務(如後台服務、緩存服務或通知服務)存取資料庫上下文、配置服務或使用者服務。
在單例服務中使用作用域服務的主要挑戰是手動管理作用域的生存期和處置。由於單一例項服務沒有請求作用域,因此需要使用 建立作用域,並在完成作用域服務後釋放它。您還需要使用 或 等方法從作用域的服務提供程式解析作用域服務。IServiceScopeFactoryGetRequiredServiceGetService
如果未正確建立和釋放作用域,則可能會遇到錯誤或記憶體泄漏等錯誤。您還需要處理在作用域內使用作用域服務時可能發生的任何異常。InvalidOperationException: Cannot resolve scoped service from root provider
可能需要在單一例項服務中使用作用域內服務的一些方案範例包括:
定期執行的 後台服務 ,需要存取資料庫上下文才能執行某些操作。資料庫上下文是依賴於當前請求的作用域服務,因此需要手動建立作用域並解析作用域內的資料庫上下文。
public classMyBackgroundService : BackgroundService
{
privatereadonlyIServiceScopeFactory _scopeFactory;
publicMyBackgroundService(IServiceScopeFactory scopeFactory)
{
_scopeFactory = scopeFactory;
}
protectedoverrideasyncTaskExecuteAsync(CancellationToken stoppingToken)
{
// Create a scope using the CreateScope method
using (var scope = _scopeFactory.CreateScope())
{
// Resolve the database context using the GetRequiredService method
var dbContext = scope.ServiceProvider.GetRequiredService\<MyDbContext>();
// Do something with the database context
var users = await dbContext.Users.ToListAsync();
// ...
}
}
}
一種 緩存服務 ,用於儲存分布式緩存中的數據並從中檢索數據。緩存服務是由整個應用程式共享的單一例項服務,但它需要存取配置服務才能獲取緩存設定。配置服務是依賴於當前請求的作用域服務,因此需要手動建立作用域,並在作用域內解析配置服務。
public classMyCacheService
{
privatereadonlyIServiceScopeFactory _scopeFactory;
publicMyCacheService(IServiceScopeFactory scopeFactory)
{
_scopeFactory = scopeFactory;
}
// Define a method to get data from the cache
publicasyncTask<T>GetDataAsync<T>(string key)
{
// Create a scope using the CreateScope method
using (var scope = _scopeFactory.CreateScope())
{
// Resolve the configuration service using the GetService method
var configuration = scope.ServiceProvider.GetService<IConfiguration>();
// Get the cache settings from the configuration
var cacheSettings = configuration.Getp("CacheSettings").Get<CacheSettings>();
// Do something with the cache settings
var cache = newDistributedCache(cacheSettings);
// Get data from the cache
var data = await cache.GetAsync<T>(key);
return data;
}
}
}
透過電子信件或簡訊向使用者發送通知的 通知服務 。通知服務是由整個應用程式共享的單一例項服務,但它需要存取使用者服務才能獲取使用者的聯系資訊。使用者服務是依賴於當前請求的作用域服務,因此需要手動建立作用域,並在作用域內解析使用者服務。
public classMyNotificationService
{
privatereadonlyIServiceScopeFactory _scopeFactory;
publicMyNotificationService(IServiceScopeFactory scopeFactory)
{
_scopeFactory = scopeFactory;
}
// Define a method to send notifications to users
publicasyncTaskSendNotificationAsync(string message, int userId)
{
// Create a scope using the CreateScope method
using (var scope = _scopeFactory.CreateScope())
{
// Resolve the user service using the GetRequiredService method
var userService = scope.ServiceProvider.GetRequiredService<IUserService>();
// Get the user's contact information from the user service
var user = await userService.GetUserByIdAsync(userId);
var email = user.Email;
var phone = user.Phone;
// Do something with the contact information
var emailService = newEmailService();
var smsService = newSmsService();
// Send notifications to the user via email and SMS
await emailService.SendEmailAsync(email, message);
await smsService.SendSmsAsync(phone, message);
}
}
}
在單一例項服務中使用作用域服務的優點和缺點包括:
優勢 :
您可以避免使用單一例項服務存取特定於請求的數據或資源時可能出現 的並行問題 。例如,如果使用單一例項服務存取資料庫上下文,則可能會遇到 或 等錯誤。透過在單一例項服務中使用作用域內服務,可以確保每個請求都有自己的資料庫上下文例項,並避免這些錯誤。
您可以 確保正確處置 作用域內的服務及其依賴項。例如,如果使用單一例項服務存取資料庫上下文,則可能會忘記釋放它或過早釋放它,這可能會導致記憶體泄漏或數據損壞。透過在單一例項服務中使用作用域服務,可以確保在請求結束時釋放作用域,並隨請求釋放資料庫上下文。
缺點 :
您可以為程式碼和效能 增加一些復雜性和開銷 。例如,如果在單一例項服務中使用作用域服務,則需要將作用域註入到單一例項服務中,手動建立和釋放作用域,然後從作用域的服務提供程式解析作用域服務。這會為單例服務添加一些額外的程式碼和邏輯,這可能會使其更難讀取和維護。它還會增加一些額外的記憶體和 CPU 使用率,以建立和釋放作用域並解析服務,這可能會影響您的效能。
如果你喜歡我的文章,請給我一個贊!謝謝