در مطلب قبل به نحوه خواندن دیتاها از appsettings.json توسط IOptions پرداختیم. در این مطلب به بررسی تفاوت بین IOptions, IOptionsMonitor و IOptionsSnapshot میپردازیم.
اینترفیس IOptions به صورت Singleton عمل میکند و به همین دلیل میتواند در تمامی سرویس ها با هر نوع طول عمری (Lifetime) inject شود. اگر بعد از اجرای برنامه, مقدار فایل appsettings.json را تغییر دهید و از این اینترفیس برای خواندن دیتاها استفاده کرده باشید, تغییرات خود را مشاهده نمکنید, به دلیل اینکه این سرویس Singleton است و فقط در زمان اجرای برنامه مقدار دهی میشود و تا زمانی که برنامه مجددا اجرا نشود, همان مقادیر اولیه را نشان میدهد.
اینترفیس IOptionsSnapshot به صورت Scoped عمل میکند. یعنی به ازای هر ریکوست, مجددا دیتاها را از appsettings.json میخواند و در اختیار ما قرار میدهد. از این اینترفیس نمیتوان در سرویس هایی با طول عمر Singleton استفاده کرد.
اینترفیس IOptionsMonitor به صورت Singleton عمل میکند اما تفاوت آن با اینترفیس IOptions این است که اگر تغییری در فایل appsettings.json ایجاد شود, توسط متد OnChange میتوان تغییرات جدید را دریافت کرد. برای مثال یک کلاس به نام ApplicationConfig ایجاد کرده ایم که یک پراپرتی به نام Name دارد و مقدار این پراپرتی از appsettings.json خوانده میشود.
public class ApplicationConfig
{
public string Name { get; set; }
}
فایل appsettings.json:
{
"ApplicationConfig": {
"Name": "DotNetDocs"
}
}
سپس این کلاس را به متد Configure معرفی میکنیم در متد ConfigureService:
public void ConfigureServices(IServiceCollection services)
{
services.Configure<ApplicationConfig>(Configuration.GetSection(nameof(ApplicationConfig)));
//...
}
در ادامه یک کنترلر برای تست کردن مقادیر دریافت شده ایجاد میکنیم:
[Route("api/[controller]")]
[ApiController]
public class HomeController : Controller
{
private readonly ApplicationConfig _options;
private readonly ApplicationConfig _optionsSnapshot;
public HomeController(IOptions<ApplicationConfig> options, IOptionsSnapshot<ApplicationConfig> optionsSnapshot)
{
_options = options.Value;
_optionsSnapshot = optionsSnapshot.Value;
}
[HttpGet("Index")]
public IActionResult Index()
{
var options = _options.Name;
var snapshot = _optionsSnapshot.Name;
return Json(new { options = options, snapshot = snapshot });
}
}
اکنون اگر به مسیر /api/Home/Index را در مرورگر وارد کنید مقدار زیر را دریافت میکنید:
{"options":"DotNetDocs","snapshot":"DotNetDocs"}
اگر مقدار Name در فایل appsetting.json را به dntips تغییر دهید و مجددا صفحه را بارگذاری کنید, مقادیر زیر را دریافت میکنید:
{"options":"DotNetDocs","snapshot":"dntips"}
مقدار Name که از اینترفیس IOptionsSnapshot دریافت شده, تغییرات را دریافت کرده ولی اینترفیس IOptions چون به صورت Singleton رجیستر شده است تغییرات را دریافت نمیکند.
برای تست کردن نحوه کار IOptionsMonitor یک هاستد سرویس ایجاد میکنیم به نام HostedService که در سازنده آن متد OnChange را با توجه به نیاز خودمان تغییر میدهیم:
public class HostedService : BackgroundService
{
private ApplicationConfig _optionsMonitor;
public HostedService(IOptionsMonitor<ApplicationConfig> optionsMonitor)
{
_optionsMonitor = optionsMonitor.CurrentValue;
optionsMonitor.OnChange(config =>
{
_optionsMonitor = config;
});
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
var name = _optionsMonitor.Name;
await Task.Delay(1000);
}
}
}
رجیستر کردن هاست سرویس :
public void ConfigureServices(IServiceCollection services)
{
//...
services.AddHostedService<HostedService>();
}
اکنون اگر برنامه را اجرا کنید هاستد سرویس هم اجرا میشود و یک بار مقادیر را از appsettings.json میخواند و در دفعات بعدی مقدار Name را درون متغییر name قرار میدهد(در متد ExecuteAsync ). اما زمانی که تغییری در فایل appsettings.json ایجاد شود متد OnChange صدا زده میشود و مقادیر جدید را درون پارامتر config مربوط به متد OnChange قرار میدهد و با استفاده از این متد میتوانیم تغییرات جدید را دریافت کنیم و درمتغییر optionsMonitor_ قرار دهیم.
- اگر سرویسی دارید که به صورت Singleton رجیستر شده است و یکسری مقادیر را از appsettings.json میخواند, اگر دیتاها ممکن است تغییر کند بهتر است از IOptionsMonitor استفاده کنید تغییرات داده شده را اعمال کنید با استفاده از متد OnChange. از اینترفیس IOptionsMonitor بیشتر در سرویس های Singleton مانند HostedService ها استفاده میشود, چون نمیتوان از IOptionsSnapshot استفاده کرد و مجددا دیتاها را به روز رسانی کرد.
- اگر تغییرات فایل appsettings.json زیاد مهم نیستند و فورا نباید اعمال شوند میتوانید از IOptions استفاده کنید.
- اگر تغییرات فایل appsettings.json مهم هستند و باید تغییرات آنها اعمال شود میتوانید از IOptionsSnapshot استفاده کنید زیرا به ازای هر ریکوست مجددا دیتاها را از appsettings.json میخواند. از این اینترفیس نمیتوان در سرویس های Singleton استفاده کرد.
منابع :
- https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/options?view=aspnetcore-5.0
- https://stackoverflow.com/questions/50788988/difference-between-ioptionsmonitor-vs-ioptionssnapshot
- https://andrewlock.net/reloading-strongly-typed-options-in-asp-net-core-1-1-0/
;)
Powered by Froala Editor