Reflection در #C
دوشنبه 16 شهریور 1394در این مقاله با استفاده از یک مثال، درباره Reflection در #C بحث خواهیم کرد.
مقدمه:
در اینجا روش های به دست آوردن نوع اطلاعات را با استفاده از راه های مختلف و استفاده از property ها و متدهای کلاس reflection آموزش خواهیم داد. مفاهیم پیشرفته reflection مانند بارگذاری داینامیک یک فایل اسمبلی و سپس bind کردن آن، نیز در این مقاله بحث خواهد شد. برای تکمیل این آموزش، دیکشنری #C را پیاده سازی می نماییم.
reflection در #C چیست؟
reflection، اشیایی از نوع Type فراهم می کند که اسمبلی ها، ماژول ها و typeها را توصیف می کنند. می توانیم از reflection برای ایجاد داینامیک نمونه ای از نوع داده استفاده کنیم، آن را به شی موجود Bind نماییم و یا نوع داده را از شی موجود به دست آورده و به متد آن دسترسی پیدا کنیم یا به propertyها و فیلدهای آن دسترسی داشته باشیم. اگر از attributeها در کد خود استفاده کنیم، reflection این امکان را فراهم می کند که به آنها نیز دسترسی پیدا کنیم.
کد زیر مثالی از reflection با استفاده از متد استاتیک GetType است برای به دست آوردن نوع متغیر می باشد که توسط همه انواع داده های کلاس مبتنی بر Object ارث بری می شود.
// Using GetType to obtain type information: int i = 42; System.Type type = i.GetType(); System.Console.WriteLine(type);
خروجی به شکل زیر خواهد بود:
System.Int32
کد زیر نیز، از reflection برای به دست آوردن نام کامل فایل اسمبلی لود شده استفاده می کند:
// Using Reflection to get information from an Assembly: System.Reflection.Assembly info = typeof(System.Int32).Assembly; System.Console.WriteLine(info);
خروجی به شکل زیر است:
mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
پیاده سازی:
در ابتدا یک پروژه Console Application در #C ایجاد می کنیم و دو کلاس به نام Student.cs و StudentFunction.cs به آن اضافه می کنیم. کلاس Student شامل propertyهای مربوط به Student و StudentFunction شامل متدهایی است که مقادیر مختلفی برای propertyها را برمی گرداند.
کلاس Student:
public class Student { public string Name { get; set; } public string University { get; set; } public int Roll { get; set; } }
کلاس StudentFunction:
class StudentFunction { private Student student; public StudentFunction() { student = new Student { Name = "Gopal C. Bala", University = "Jahangirnagar University", Roll = 1424 }; } public string GetName() { return student.Name; } public string GetUniversity() { return student.University; } public int GetRoll() { return student.Roll; } }
هدف ما این است که به طور داینامیک یک شی از StudentFunction ایجاد کرده و در زمان کامپایل مقادیر را توسط متد ()GetName، متد ()GetUniversity و متد ()GetRoll به دست آوریم.
در Program.cs، نیاز داریم که یک دیکشنری ایجاد کنیم تا شامل نام متدها به صورت رشته باشد. این رشته با رشته خاصی که فرمت تگ داینامیک دارد به نام [tag name] مقایسه می شود، اگر مطابقت داشت، باید نوع متد را به دست آوریم.
این دیکشنری به صورت زیر خواهد بود:
private static Dictionary<string, string> GetMethodsDictionary() { var dictionary = new Dictionary<string, string> { {"GetName", "GetName"}, {"GetUniversity", "GetUniversity"}, {"GetRoll","GetRoll"} }; return dictionary; }
در main مربوط به Program.cs، متد ()GetMethodsDictionary را صدا می زنیم.
_methodDictionary = new Dictionary<string, string>(); _methodDictionary = GetMethodsDictionary();
حال کد مربوط به ایجاد شی از کلاس StudentFunction را در زمان کامپایل را می نویسیم:
var type = typeof(StudentFunction); var studentFunctionInstance = Activator.CreateInstance(type, new object[] { });
رشته موردنظر به صورت زیر خواهد بود که شامل تگ های داینامیک بر اساس مقادیری است که می خواهیم بازیابی کنیم.
var testString = "Hello [GetName], your university name is [GetUniversity] and roll is [GetRoll]";
در اینجا، [GetName] و [GetUniversity] و همچنین [GetRoll] در واقع نام متدهایی است که باید با متدهای تعریف شده در StudentFunction مقایسه شوند.
حال این تگ ها را با استفاده از Regular expression بررسی می کنیم و مقادیر دریافت شده از متدهای StudentFunction را به آنها نسبت می دهیم.
var match = Regex.Matches(testString, @"\[([A-Za-z0-9\-]+)]", RegexOptions.IgnoreCase); foreach (var v in match) { var originalString = v.ToString(); var x = v.ToString(); x = x.Replace("[", ""); x = x.Replace("]", ""); x = _methodDictionary[x]; var toInvoke = type.GetMethod(x); var result = toInvoke.Invoke(studentFunctionInstance, null); testString = testString.Replace(originalString, result.ToString()); }
بنابراین کلاس Program.cs به طور کلی به شکل زیر خواهد بود:
class Program { private static Dictionary<string, string> _methodDictionary; static void Main(string[] args) { _methodDictionary = new Dictionary<string, string>(); _methodDictionary = GetMethodsDictionary(); var type = typeof(StudentFunction); var studentFunctionInstance = Activator.CreateInstance(type); var testString = "Hello [GetName], your university name is [GetUniversity] and roll is [GetRoll]"; var match = Regex.Matches(testString, @"\[([A-Za-z0-9\-]+)]", RegexOptions.IgnoreCase); foreach (var v in match) { var originalString = v.ToString(); var x = v.ToString(); x = x.Replace("[", ""); x = x.Replace("]", ""); x = _methodDictionary[x]; var toInvoke = type.GetMethod(x); var result = toInvoke.Invoke(studentFunctionInstance, null); testString = testString.Replace(originalString, result.ToString()); } Console.WriteLine(testString); } private static Dictionary<string, string> GetMethodsDictionary() { var dictionary = new Dictionary<string, string> { {"GetName", "GetName"}, {"GetUniversity", "GetUniversity"}, {"GetRoll","GetRoll"} }; return dictionary; } }
خروجی این برنامه به شکل زیر می باشد:
- C#.net
- 2k بازدید
- 3 تشکر