MVVM Part 8 – the MEF Library

22 בFebruary 2013

אין תגובות

אחרי שעשינו היכרות בסיסית עם Unity, נשלים את התמונה עם הContainer הפופולרי הנוסף הלא הוא MEF

את קוד
המקור של
MEF  אפשר
להוריד
מכאן, ובכל
מקרה הספרייה המצאת לכם בכך מקרה בתוך דוט נט 4 ומעלה. פשוט הוסיפו רפרנס ל
DLL בשם System.ComponentModel.Composition,MEF רואי לציין ש
 כספרייה נחשבת כתומכת גם באובייקטים של Third Party. זאת אומרת ניתן להכיל אותה ולבצע
“הזרקת התנהגות” גם עם קונטרולים של יצרן פרטי וצורת העבודה היא לכאורה
דינמית יותר מ
Unity בזה שאני לא רושם בקוד
תלות בטייפ מסויים אלא משתמש ב
Attribute ומוסיף מתי שבא לי איפה
שבא לי.

השימוש בAttribute מוכר כMarker
Interface Pattern
,  וMEF זאת דוגמא נהדרת מה אפשר לעשות עם Attribute ואנחנו לא עושים בד”כ וחבל…

הרעיון
המרכזי של עבודה עם
MEF  הוא הוספת Attributes לאובייקטים שמייצגים או Import או export. בעברית פשוטה יבוא-יצוא.
ובכן, מה אני מייצא ומה אני מייבא? ובכן זה פשוט מאוד, פונקציונאליות.

נציג דוגמא
בסיסית כיצד לבנות אפליקציה בעזרת
MEF:

א.    
נפתח
פרוייקט
consol ונוסיף רפרנס ל2 הבאים מתוך MEF   2 אלו זה המינימום ההכרחי.

 

using System.ComponentModel.Composition;

using System.ComponentModel.Composition.Hosting;

 

ב.    
בוא
נחליט על שירות מסוים שנרצה להוסיף לאפליקציה מאוחר יותר באמצעות
Injection . אני בוחר לצורך הדוגמא ביכולת הדפסה
כלשהי, אני מגדיר חוזה שיהווה את הטייפ שיהיה מוכר במערכת, ואני עושה לו מימוש
בסיסי, בחרתי להשתמש ב <
T> אבל אפשר גם בלי,
הנקודה החשובה היא השימוש ב
Attribute  Export של MEF,  שאומר אני רוצה להיות מסוגל להעביר שירות מסוג
הטייפ שמופיע ב
Attribute כשהמימוש הספציפי יצביע
אליי באובייקט.

 public interface IPrinter<T>

    {

        void PrintValue<T>(T args);

    }

 

    [Export(typeof(IPrinter<object>))]

     class Printer:IPrinter<object>

    {

        public void PrintValue<T>(T args)

        {

            Console.WriteLine(args.ToString());

        }

    }

ג.     
כמו תמיד
כשמדברים במונחי
IOC, צריך שיהיה לנו קונטיינר
שמכיל את כל השירותים באפליקציה, אז ב
Program אני כותב את הקוד הבא:

 class Program

    {

        private CompositionContainer container;

        [Import(typeof(IPrinter<object>))]

        private IPrinter<object> printer;

 

        private Program()

        {

            var catalog = new AggregateCatalog();

            catalog.Catalogs.Add(new AssemblyCatalog(this.GetType().Assembly));

            container = new CompositionContainer(catalog);

            container.ComposeParts(this);

 

        }

 

אני רואה  שהוספתי את הדברים
הבאים:

קונסטרקטור, קטלוג, קונטיינר, ורפרנס פרטי לטיפוס IPrinter שמשתמש ב Import .

מה זה אומר? (נתעלם מהקונסטרקטור, בהנחה שברור מה זה אומר..) Catalog משמש לרישום אובייקטים לתוך הContainer. שזה מאפשר לי ליצור חלוקה פנימית בקונטיינר
עצמו ואז לשלוף לפי הצורך קטלוג שלם באיזשהו מקום ברחבי הגלקסיה, (סליחה,
האפליקציה).

הקונטיינר עצמו זה די פשוט כמו כל IOC Container, באמצעותו ניתן ל”הזריק
שירותים” בזמן ריצה.

לצורך הקיצור שבדוגמא אני משתמש בProgram כקטלוג וקונטיינר בו
זמנית, ולכן נשים לב שאני רושם את הטייפ של עצמי כ
Assembly
Catalog
לקטלוג, ואז מכניס אותו לContainer. מה שנשאר זה ל”פבלש” את הקטלוגים
שישנם בקונטיינר (לתת לו את האחריות לחפש מימושים באמצעות
import/export )

 

ד.     
לצורך
בדיקה אני מוסיף אובייקט קטנטן:

 
   public class taster
    {
        public taster()
        {
 
        }
    }

ואז מריץ מתוך הmain:

 static void Main(string[] args)
        {
            Program p = new Program();
            p.printer.PrintValue<taster>(new taster());
        }

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

כמובן שיש המון דברים שלא נכנסתי אליהם אלא זה היה ברמת מבוא.

 

הוסף תגובה
facebook linkedin twitter email

Leave a Reply

Your email address will not be published. Required fields are marked *