Menu
Coddy logo textTech

מאפיינים ורפלקציה

חלק מהיחידה תכנות מונחה עצמים במסלול ה-C# של Coddy. שיעור 44 מתוך 70.

מאפיינים הם תגיות מטא־נתונים שמצמידים לרכיבי קוד כמו מחלקות, מתודות או מאפיינים. הם לא משנים ישירות את אופן הביצוע של הקוד, אבל מספקים מידע שאפשר לקרוא בזמן ריצה. Reflection הוא המנגנון שקורא את המטא־נתונים האלה.

מחילים מאפיין על ידי הצבתו בסוגריים מרובעים מעל לרכיב היעד:

[Obsolete("Use NewMethod instead")]
public void OldMethod() { }

[Serializable]
public class Person
{
    public string Name { get; set; }
}

אפשר ליצור מאפיינים מותאמים אישית באמצעות ירושה מ־Attribute:

public class AuthorAttribute : Attribute
{
    public string Name { get; }
    public AuthorAttribute(string name) => Name = name;
}

[Author("John")]
public class Calculator { }

שיקוף מאפשר לך לבדוק טיפוסים ולקרוא מאפיינים בזמן ריצה באמצעות מרחב השמות System.Reflection:

Type type = typeof(Calculator);
var attr = type.GetCustomAttribute<AuthorAttribute>();
Console.WriteLine(attr.Name);  // John

אפשר גם לגלות מתודות ומאפיינים ולהפעיל אותם באופן דינמי:

MethodInfo[] methods = type.GetMethods();
foreach (var method in methods)
    Console.WriteLine(method.Name);

תכונות והשתקפות עומדות בבסיסם של מסגרות עבודה רבות – ספריות לסריאליזציה משתמשות בהן כדי לשלוט בפלט JSON, מסגרות עבודה לבדיקות משתמשות בהן כדי לגלות מתודות בדיקה, ומכלי הזרקת תלות משתמשים בהן כדי לחבר שירותים באופן אוטומטי.

challenge icon

אתגר

קל

בואו נבנה מערכת לגילוי תוספים שמשתמשת במאפיינים מותאמים אישית ובהשתקפות כדי למצוא ולתאר אוטומטית מחלקות המסומנות כתוספים. הדבר דומה לאופן שבו מסגרות עבודה אמיתיות מגלות רכיבים, מתודות בדיקה או נקודות קצה של API בזמן ריצה.

תארגנו את הקוד שלכם בשלושה קבצים:

  • PluginAttribute.cs: צרו מאפיין מותאם אישית בשם PluginAttribute במרחב השמות PluginSystem. המאפיין שלכם צריך:
    • לרשת מ-Attribute
    • להכיל שתי תכונות לקריאה בלבד: Name (מחרוזת) ו-Version (מחרוזת)
    • לקבל את שני הערכים באמצעות הבנאי שלו
  • Plugins.cs: צרו כמה מחלקות של תוספים במרחב השמות PluginSystem. חלקן צריכות להיות מעוטרות ב-PluginAttribute שלכם, ואחת לא:
    • ImageProcessor - מסומנת באמצעות [Plugin("Image Processor", "1.0")]
    • DataExporter - מסומנת באמצעות [Plugin("Data Exporter", "2.5")]
    • HelperUtility - לא מסומנת בשום מאפיין (זו פשוט מחלקה רגילה)
    כל מחלקה יכולה להיות ריקה - אנחנו מעוניינים רק לגלות את המטא-נתונים שלהן באמצעות השתקפות.
  • Program.cs: בקובץ הראשי שלכם, השתמשו בהשתקפות כדי לגלות את כל המחלקות שיש להן את PluginAttribute. עבור כל תוסף שיתגלה, הדפיסו את המידע שלו. תצטרכו:
    • לקבל את כל הטיפוסים מהאסמבלי הנוכחי
    • לבדוק כל טיפוס כדי לראות אם יש לו את PluginAttribute
    • לחלץ ולהציג את התכונות Name ו-Version של המאפיין

השתמשו ב-System.Reflection כדי לבדוק טיפוסים ולאחזר מאפיינים מותאמים אישית. המתודה GetCustomAttribute<T>() מחזירה את null אם המאפיין אינו קיים, כך שתוכלו להשתמש בכך כדי לסנן את המחלקות שהן תוספים בפועל.

הדפיסו כל תוסף שהתגלה בפורמט הבא, אחד בכל שורה:

Plugin: {Name} (v{Version})

יש להדפיס את התוספים לפי הסדר הבא: ImageProcessor תחילה, ואז DataExporter. המחלקה HelperUtility לא אמורה להופיע בפלט, משום שאין לה את המאפיין.

פלט צפוי:

Plugin: Image Processor (v1.0)
Plugin: Data Exporter (v2.5)

האתגר הזה מדגים כיצד מסגרות עבודה משתמשות במאפיינים כסמנים ובהשתקפות כדי לגלות אותם - אותה טכניקה עומדת בבסיס מכלי הזרקת תלות, ספריות סריאליזציה ומסגרות בדיקה!

נסו בעצמכם

using System;
using System.Reflection;
using PluginSystem;

class Program
{
    public static void Main(string[] args)
    {
        // TODO: קבל את כל הטיפוסים מהאסמבלי הנוכחי
        // רמז: השתמש ב-Assembly.GetExecutingAssembly().GetTypes()
        
        // TODO: עבור על כל טיפוס ובדוק אם יש לו PluginAttribute
        // רמז: השתמש ב-type.GetCustomAttribute<PluginAttribute>()
        
        // TODO: אם המאפיין קיים, הדפס את פרטי התוסף בפורמט:
        // Plugin: {Name} (v{Version})
        
    }
}
quiz iconבחנו את עצמכם

השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.

כל השיעורים ביחידה תכנות מונחה עצמים

תרגלו בעצמכם: קומפיילר C# אונליין