مقدمه

در بسیاری از برنامه‌ها، مقادیر و تنظیماتی وجود دارند که نمی‌خواهیم آن‌ها را به صورت ثابت در کد (hard-code) بنویسیم. این مقادیر ممکن است بین محیط‌های مختلف (مانند توسعه، تست و تولید) متفاوت باشند یا نیاز به تغییر آن‌ها بدون کامپایل مجدد برنامه وجود داشته باشد. مثال‌های رایج شامل رشته‌های اتصال به پایگاه داده، کلیدهای API، یا تنظیمات مربوط به رفتار برنامه هستند. برای مدیریت این داده‌ها، از فایل‌های پیکربندی (Configuration Files) استفاده می‌کنیم. در .NET مدرن، سیستم پیکربندی بسیار انعطاف‌پذیر است و به ما اجازه می‌دهد تا تنظیمات را از منابع مختلفی مانند فایل‌های JSON، متغیرهای محیطی یا آرگومان‌های خط فرمان بخوانیم.

فایل appsettings.json

در پروژه‌های مدرن .NET (به خصوص در ASP.NET Core و اپلیکیشن‌های کنسول جدید)، فرمت استاندارد برای فایل‌های پیکربندی، JSON (JavaScript Object Notation) است. فایل اصلی پیکربندی معمولاً appsettings.json نام دارد. این فایل به ما اجازه می‌دهد تا تنظیمات را به صورت یک ساختار سلسله مراتبی از جفت‌های کلید-مقدار ذخیره کنیم.

برای استفاده از این سیستم، باید چند پکیج NuGet را به پروژه‌ی خود اضافه کنیم:

  • Microsoft.Extensions.Configuration
  • Microsoft.Extensions.Configuration.Json
  • Microsoft.Extensions.Configuration.Binder

یک نمونه از فایل appsettings.json می‌تواند به شکل زیر باشد:

Copy Icon appsettings.json
{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning"
    }
  },
  "ConnectionStrings": {
    "DefaultConnection": "Server=.;Database=MyDb;Trusted_Connection=True;"
  },
  "AppTitle": "My Awesome App"
}

خواندن مقادیر از فایل کانفیگ

برای خواندن این تنظیمات در برنامه، از یک ConfigurationBuilder استفاده می‌کنیم. این کلاس به ما اجازه می‌دهد تا منابع مختلف پیکربندی را به ترتیب اولویت اضافه کنیم.

Copy Icon Program.cs
using Microsoft.Extensions.Configuration;

// Build configuration
IConfiguration config = new ConfigurationBuilder()
    .SetBasePath(Directory.GetCurrentDirectory()) // Set the base path to the app's folder
    .AddJsonFile("appsettings.json", optional: false) // Add the JSON file as a source
    .Build();

// Read a simple value
string title = config["AppTitle"];
Console.WriteLine($"App Title: {title}");

// Read a nested value using a colon-separated path
string connectionString = config["ConnectionStrings:DefaultConnection"];
Console.WriteLine($"Connection String: {connectionString}");

در این کد، ما یک ConfigurationBuilder ایجاد کرده، مسیر پایه‌ی برنامه را به آن می‌دهیم و فایل appsettings.json را به عنوان یک منبع اضافه می‌کنیم. سپس با استفاده از سینتکس ایندکسر و یک مسیر که با دو نقطه `:` از هم جدا شده، به مقادیر تودرتو دسترسی پیدا می‌کنیم.

الگوی Options: اتصال کانفیگ به اشیاء

خواندن تک‌تک مقادیر با استفاده از رشته‌ها می‌تواند مستعد خطا و تکراری باشد. یک الگوی بسیار بهتر و امن‌تر، استفاده از الگوی Options است. در این الگو، ما یک کلاس POCO (Plain Old CLR Object) تعریف می‌کنیم که ساختار آن دقیقاً با بخشی از فایل JSON ما مطابقت دارد. سپس از سیستم پیکربندی می‌خواهیم تا آن بخش از کانفیگ را به یک نمونه از کلاس ما "متصل" (bind) کند.

فرض کنید می‌خواهیم تنظیمات مربوط به Logging را در یک کلاس ذخیره کنیم.

Copy Icon Settings.cs
public class LoggingSettings
{
    public LogLevelSettings LogLevel { get; set; }
}
public class LogLevelSettings
{
    public string Default { get; set; }
    public string Microsoft { get; set; }
}

حالا می‌توانیم بخش Logging از فایل appsettings.json را به یک نمونه از این کلاس متصل کنیم.

Copy Icon Program.cs
// Get a specific section of the configuration
IConfigurationSection loggingSection = config.GetSection("Logging");

// Bind the section to an instance of our settings class
LoggingSettings settings = new();
loggingSection.Bind(settings);

Console.WriteLine($"\nDefault Log Level: {settings.LogLevel.Default}");

متد Bind به صورت هوشمند پراپرتی‌های کلاس را با کلیدهای موجود در بخش کانفیگ تطبیق داده و مقادیر را به آن منتقل می‌کند. این روش کد را بسیار تمیزتر کرده و از خطاهای ناشی از رشته‌های جادویی (magic strings) جلوگیری می‌کند.