العمل مع YAML في C# (.NET): المكتبات والأمثلة العملية
YAML (YAML Ain't Markup Language) هو تنسيق شائع لتسلسل البيانات، يُستخدم على نطاق واسع لملفات التكوين، DevOps (Ansible, Kubernetes, Docker Compose) وتبادل البيانات. في بيئة .NET، لا يوجد دعم مدمج لـ YAML، ولكن توجد مكتبات خارجية قوية. في هذه المقالة، سنستعرض مكتبتين رئيسيتين: YamlDotNet (الأكثر شيوعًا) و SharpYaml (بديل خفيف)، وسنوضح كيفية دمجهما في مشاريع C#.
1. لماذا نختار YAML بدلاً من JSON/XML؟
- بناء جملة قابل للقراءة البشرية مع مسافات بادئة (بدون أقواس أو علامات اقتباس).
- دعم التعليقات (تبدأ بـ #).
- دعم مدمج للهياكل المعقدة (قوائم، قواميس، نصوص متعددة الأسطر).
- المعيار الفعلي للتكوينات في الحاويات و CI/CD.
2. المكتبة الأساسية: YamlDotNet
YamlDotNet هي المكتبة الأكثر نضجًا والمدعومة لـ .NET (بما في ذلك .NET Core, .NET 5+). توفر دورة كاملة: إلغاء التسلسل (YAML ← كائنات C#) والتسلسل (كائنات ← YAML).
2.1 التثبيت عبر NuGet
dotnet add package YamlDotNetأو عبر مدير الحزم في Visual Studio: Install-Package YamlDotNet.
2.2 إلغاء التسلسل الأساسي
لنفترض أن لدينا ملف config.yaml:
# إعدادات التطبيقapp: name: MyApp version: 1.0.0 debug: false
database: host: localhost port: 5432 credentials: user: admin password: secretلننشئ الفئات المقابلة في C#:
public class AppConfig{ public string Name { get; set; } public string Version { get; set; } public bool Debug { get; set; }}
public class DatabaseConfig{ public string Host { get; set; } public int Port { get; set; } public Credentials Credentials { get; set; }}
public class Credentials{ public string User { get; set; } public string Password { get; set; }}
public class RootConfig{ public AppConfig App { get; set; } public DatabaseConfig Database { get; set; }}الآن نقوم بتحليل YAML إلى كائنات:
using YamlDotNet.Serialization;using YamlDotNet.Serialization.NamingConventions;
var yamlContent = File.ReadAllText("config.yaml");
var deserializer = new DeserializerBuilder() .WithNamingConvention(UnderscoredNamingConvention.Instance) // للشرطات السفلية .Build();
var config = deserializer.Deserialize<RootConfig>(yamlContent);
Console.WriteLine($"App: {config.App.Name} v{config.App.Version}");Console.WriteLine($"DB host: {config.Database.Host}:{config.Database.Port}");2.3 تسلسل الكائنات إلى YAML
var serializer = new SerializerBuilder() .WithNamingConvention(CamelCaseNamingConvention.Instance) .Build();
var config = new RootConfig{ App = new AppConfig { Name = "TestApp", Version = "2.0.0", Debug = true }, Database = new DatabaseConfig { Host = "192.168.1.1", Port = 3306, Credentials = new Credentials { User = "root", Password = "qwerty" } }};
string yamlOutput = serializer.Serialize(config);Console.WriteLine(yamlOutput);2.4 العمل مع البيانات الديناميكية
إذا كان هيكل YAML غير معروف مسبقًا، استخدم Dictionary<object, object>:
var deserializer = new DeserializerBuilder() .Build();
var result = deserializer.Deserialize<Dictionary<object, object>>(yamlContent);// اجتياز القاموس بشكل متكررPrintYaml(result, 0);
void PrintYaml(Dictionary<object, object> dict, int indent){ foreach (var kvp in dict) { Console.WriteLine($"{new string(' ', indent * 2)}{kvp.Key}: {kvp.Value}");