היום נראה דוגמה נחמדה לשימוש בAttributeים.
נניח שאנחנו רוצים לממש Factory של צורות, כלומר מחלקה אשר בונה לנו instance של צורה לפי השם שלה.
ראינו שני סוגי מימושים בטיפים שמספרם 50 ו139.
תזכורת: המימוש הכי פשוט הוא משהו כזה:
|
|
אבל הוא גם המימוש הכי מכוער.
מה שנעשה הפעם, זה נשתמש בAttribute משלנו שנוכל לשים מעל מתודה של המחלקה שלנו, בו נציין את שם הצורה שהמתודה מספקת, ונקרא למתודה בצורה מתאימה בעזרת Reflection.
אז יאללה, לעבודה!
מה שאנחנו מעוניינים לעשות זה למפות מתודה, לשם של הצורה אותה היא יוצרת. כלומר, בסופו של דבר לכתוב מחלקה שנראית כך:
|
|
המתודה CreateByName תדע לאיזו מתודה (למתודה כזו אני אוהב לקרוא Builder) ללכת לפי הstring שמצוין בAttribute מעליה.
תחשבו שבמתודות הBuilderים, יכולה להיות לוגיקה יותר מסובכת…
זה מזכיר קצת את טיפ מספר 50, אבל גם קצת שונה.
ראשית עלינו לממש את הAttribute. זה די קל:
|
|
שימו לב שאנחנו שמים AttributeUsage של מתודות בלבד.
כעת, נוכל לשים את הAttribute על מתודות שלנו, אבל חסר לנו המימוש של הפונקציה CreateByName.
המימוש שלה הוא לא קשה:
|
|
הפונקציה עשויה להראות מסובכת, אבל כל מה שקורה כאן זה שמתבצע חיפוש על כל הפונקציות הסטטיות של המחלקה ואנחנו מחפשים פונקציה שיש מעליה ShapeBuilderAttribute עם Name שזהה לname שקיבלנו.
אחרי זה אנחנו קוראים לה ועושים הסבה לShape. ראו גם טיפים מספר 95,97,147,148,154,167,168.
כעת נוכל לקרוא לפונקציה:
|
|
די מגניב.
יש פה חסרון שיש פה קריאה איטית בReflection. הראתי פעם (טיפ מספר 151) כיצד ניתן לשפר זאת באמצעות Delegate.CreateDelegate.
אפשר להשתמש בטריק הזה גם פה, וזה אפילו מתאים מאוד כי המחלקה סטטית, ולכן מספיק לאתחל אותה פעם אחת בצורה דומה לזו בConstructor הסטטי שלה.
הרעיון הוא ליצור Dictionary<string, Func<Shape>> סטטי שיכיל מיפוי של השמות לBuilderים (כמו בטיפ מספר 50) ולמלא אותו בפונקציות שיש מעליהן Attribute בConstructor הסטטי באמצעות הפונקציה Delegate.CreateDelegate. אולי אני אראה איך עושים את זה מתישהו.
המשך ערב בר סגולה