كيفية الحصول على قيمة خاصية بالاسم عبر الانعكاس في C#: شرح للمبتدئين
\n\nتخيل موقفًا: أنت تكتب كودًا تحتاج فيه إلى الوصول ديناميكيًا، بشكل فوري، إلى خاصية كائن. اسم هذه الخاصية يأتي، على سبيل المثال، من ملف إعدادات، أو من طلب JSON، أو يتم إدخاله بواسطة المستخدم. لا يمكنك كتابة object.PropertyName بشكل ثابت - لأنك لا تعرف الاسم مسبقًا. ما الحل؟
هنا يأتي دور الانعكاس (reflection) - وهي آلية قوية في C# تسمح بفحص أنواع البيانات وأعضائها (الخصائص، الدوال، الحقول) أثناء تنفيذ البرنامج. في هذه المقالة، سنشرح السؤال الأكثر شيوعًا على Stack Overflow: كيفية الحصول على قيمة خاصية كائن من سلسلة نصية تحتوي على اسمها. سنشرح ذلك بأمثلة حقيقية، من البسيط إلى المعقد، وسنناقش الأخطاء الشائعة التي يقع فيها المبتدئون.
\n\nما هو الانعكاس ولماذا نحتاجه؟
\n\nالانعكاس في C# هو قدرة البرنامج على "النظر إلى نفسه" والحصول على معلومات حول أنواعه الخاصة. توفر مساحة الأسماء System.Reflection فئات مثل Type و PropertyInfo و MethodInfo، والتي تسمح لك بما يلي:
- \n
- معرفة جميع الخصائص والدوال في الفئة. \n
- إنشاء نسخ من الفئات بدون استخدام العامل
new. \n - استدعاء الدوال والحصول على/تعيين قيم الخصائص باستخدام أسمائها النصية. \n
بدون الانعكاس، لن تتمكن، على سبيل المثال، من كتابة مابر كائنات عام (مثل AutoMapper) أو مسلسل (Serializer) يعمل مع أي نوع بيانات.
\n\nمثال أساسي: الحصول على قيمة خاصية بالاسم
\n\nلنفترض أن لدينا فئة بسيطة Person:
public class Person\n{\n public string Name { get; set; }\n public int Age { get; set; }\n public string City { get; set; }\n}\n\nنريد كتابة دالة تأخذ كائنًا من نوع Person وسلسلة نصية باسم الخاصية (مثل "Name" أو "Age") وتعيد قيمة تلك الخاصية. إليك كيفية القيام بذلك باستخدام الانعكاس:
using System;\nusing System.Reflection;\n\npublic static object GetPropertyValue(object obj, string propertyName)\n{\n if (obj == null) throw new ArgumentNullException(nameof(obj));\n if (string.IsNullOrEmpty(propertyName)) throw new ArgumentException("اسم الخاصية لا يمكن أن يكون فارغًا", nameof(propertyName));\n\n // الحصول على نوع الكائن\n Type type = obj.GetType();\n\n // الحصول على معلومات الخاصية باسمها\n PropertyInfo propertyInfo = type.GetProperty(propertyName);\n\n // التحقق من وجود الخاصية\n if (propertyInfo == null)\n throw new ArgumentException($"الخاصية '{propertyName}' غير موجودة في النوع '{type.Name}'");\n\n // الحصول على قيمة الخاصية\n return propertyInfo.GetValue(obj);\n}\n\nالآن نستخدم الدالة:
\n\nvar person = new Person { Name = "آنا", Age = 30, City = "موسكو" };\n\nstring name = (string)GetPropertyValue(person, "Name");\nint age = (int)GetPropertyValue(person, "Age");\n\nConsole.WriteLine($"الاسم: {name}, العمر: {age}"); // الإخراج: الاسم: آنا, العمر: 30\n\nكل شيء يعمل! النقاط الرئيسية:
\n- \n
obj.GetType()- يحصل على كائنTypeالذي يصف نوع الكائن الخاص بنا. \n type.GetProperty("Name")- يبحث عن خاصية عامة بالاسم "Name". يُرجعPropertyInfoأوnullإذا لم يتم العثور على الخاصية. \n propertyInfo.GetValue(obj)- يُرجع قيمة هذه الخاصية للنسخة المحددةobj. \n
ملاحظات هامة وأخطاء شائعة (ما لا يخبرك به المبتدئون)
\n\n1. حساسية حالة الأحرف
\nالدالة GetProperty بشكل افتراضي حساسة لحالة الأحرف. إذا حددت "name" بدلاً من "Name"، فلن يتم العثور على الخاصية