วิธีการทำงานกับ Managed Extensibility Framework ใน C #

MEF (Managed Extensibility Framework) เป็นส่วนประกอบที่มาพร้อมกับ. Net Framework 4 (หรือสูงกว่า) และช่วยให้คุณสร้างแอปพลิเคชันที่มีน้ำหนักเบาและขยายได้โดยใช้สถาปัตยกรรมที่มีลักษณะคล้ายปลั๊กอินที่เชื่อมต่อกันอย่างหลวม ๆ คุณสามารถใช้ประโยชน์จากเฟรมเวิร์กนี้เพื่อค้นหาและใช้ประโยชน์จากส่วนขยายได้โดยไม่จำเป็นต้องกำหนดค่าใด ๆ ในการใช้ MEF คุณสามารถปรับปรุงความยืดหยุ่นการบำรุงรักษาและความสามารถในการทดสอบแอปพลิเคชันของคุณได้อย่างง่ายดาย เมื่อใช้ MEF คุณสามารถใช้ส่วนขยายซ้ำภายในแอปพลิเคชันเดียวกันหรือแม้กระทั่งข้ามแอปพลิเคชัน

MSDN ระบุว่า: "Managed Extensibility Framework หรือ MEF เป็นไลบรารีสำหรับการสร้างแอปพลิเคชันที่มีน้ำหนักเบาและขยายได้ช่วยให้นักพัฒนาแอปพลิเคชันสามารถค้นพบและใช้ส่วนขยายโดยไม่ต้องกำหนดค่าใด ๆ นอกจากนี้ยังช่วยให้นักพัฒนาส่วนขยายสามารถห่อหุ้มโค้ดได้อย่างง่ายดายและหลีกเลี่ยงการพึ่งพาฮาร์ด MEF ไม่เพียง แต่อนุญาตให้ใช้ส่วนขยายซ้ำภายในแอปพลิเคชันเท่านั้น แต่ยังสามารถใช้กับแอปพลิเคชันต่างๆได้อีกด้วย”

DI, IoC และ MEF

DI (Dependency Injection) เป็นการทำให้หลักการ IoC (Inversion of Control) เป็นจริง ระบุว่าเมื่อวัตถุขึ้นอยู่กับวัตถุอื่นควรสร้างวัตถุดังกล่าวโดยใช้กรอบงานหรือส่วนประกอบแยกต่างหาก แม้ว่า IoC จะมีความสามารถในการปรับเปลี่ยนการดำเนินการตามสัญญา แต่ DI คือความสามารถในการจัดเตรียมการใช้งานที่จำเป็นเมื่อถูกร้องขอ โปรดทราบว่าคุณควรใช้คอนเทนเนอร์ IoC เมื่อการอ้างอิงของคุณเป็นแบบคงที่ - หากเป็นแบบไดนามิก MEF จะมีประโยชน์กว่ามาก โดยทั่วไปคอนเทนเนอร์ DI ให้การสนับสนุนสำหรับ Object Composition, Lifetime Management และ Interception

ตรงกันข้ามกับคอนเทนเนอร์ฉีดพึ่งพาทั่วไปเช่น Unity, NInject, Castle Windsor MEF ให้การสนับสนุนสำหรับองค์ประกอบของวัตถุเท่านั้น MEF ช่วยให้คุณสามารถขยายปลั๊กอินซึ่งเป็นคุณลักษณะที่คอนเทนเนอร์ IOC ทั่วไปไม่รองรับ

MEF เป็นไลบรารีที่มีการจัดการซึ่งรวมอยู่ในส่วนหนึ่งของ. Net Framework เวอร์ชันล่าสุด (ตั้งแต่. Net Framework 4 เพื่อให้แม่นยำยิ่งขึ้น) เพื่อค้นหาส่วนขยายผ่านองค์ประกอบโดยไม่ต้องมีการกำหนดค่าใด ๆ ส่วนประกอบใน MEF เรียกว่าเป็นส่วนหนึ่ง ส่วนหนึ่งระบุการอ้างอิงและความสามารถอย่างเปิดเผย การอ้างอิงเหล่านี้เรียกว่า "การนำเข้า" และความสามารถจะแสดงผ่าน "การส่งออก" โปรดทราบว่าส่วนหนึ่งควรมีแอตทริบิวต์ "ส่งออก" ที่กล่าวถึง

เริ่มต้นใช้งาน

เมื่อทำงานกับ MEF คุณสามารถใช้วิธีใดวิธีหนึ่งจากสองวิธีนี้ ซึ่งรวมถึง: วิธีการตามแอตทริบิวต์และตามแบบแผน เมื่อใช้แบบเดิมคุณมักจะใช้ประโยชน์จากแอตทริบิวต์ในโค้ดของคุณ ในทางตรงกันข้ามในตอนหลังคุณจะต้องสร้างชุดของกฎจากนั้นกำหนดกฎที่ใช้และกฎเหล่านั้นที่ใช้ไม่ได้ ในตัวอย่างนี้เราจะสำรวจแนวทางแรก

MEF ช่วยให้คุณสามารถขยายได้ผ่านเฟรมเวิร์กปลั๊กอิน เนมสเปซ System.Composition ให้การสนับสนุนสำหรับ MEF ใน. Net ในการเริ่มต้นใช้งาน MEF ในแอปพลิเคชันของคุณคุณควรรวมชุด System.Composition เพื่ออ้างอิงถึงโครงการของคุณ

ตอนนี้ให้พิจารณาอินเทอร์เฟซต่อไปนี้ชื่อ ILogger ที่ระบุด้านล่าง

public interface ILogger

   {

       string Message { get; set; }

   }

The following classes FileLogger and DbLogger implement the ILogger interface.

[Export]

   public class FileLogger : ILogger

   {      

       public string Message

       {

           get;set;

       }

   }

[Export]

   public class DbLogger : ILogger

   {

       public string Message

       {

           get; set;

       }

   }

ในตอนแรกคุณอาจคิดว่า MEF เป็นเหมือนคอนเทนเนอร์ DI อย่างไรก็ตามแม้ว่า MEF จะดูเหมือนคอนเทนเนอร์ DI แต่ก็มุ่งเป้าไปที่ความสามารถในการขยายได้เป็นหลัก โดยพื้นฐานแล้ว MEF ใช้ประโยชน์จากกลไกการค้นพบแอตทริบิวต์เพื่อส่งเสริมความสามารถในการขยายความจำเป็นในการกำหนดค่าส่วนประกอบ คุณไม่จำเป็นต้องลงทะเบียนใด ๆ คุณเพียงแค่ต้องทำเครื่องหมายประเภทของคุณด้วยแอตทริบิวต์การส่งออกและทั้งหมดนี้จะทำเพื่อคุณ ไม่เหมือนกับ Unity เมื่อใช้ MEF คุณสามารถทำเครื่องหมายชั้นเรียนโดยใช้แอตทริบิวต์โดยไม่จำเป็นต้องลงทะเบียนทีละชั้น ค่าที่ส่งออกทั้งหมดจะถูกเก็บไว้ในคอนเทนเนอร์ คลาสต่อไปนี้แสดงวิธีสร้างคอนเทนเนอร์ MEF แบบกำหนดเองและจัดเก็บการเอ็กซ์พอร์ตทั้งหมดจากไดเร็กทอรีที่มีแอสเซมบลีการรันปัจจุบันอยู่

public static class MEFContainer

   {

       private static CompositionContainer compositionContainer = null;

       public static CompositionContainer Container

       {

           get

           {

               if (compositionContainer == null)

               {

                   var directoryCatalog =

                        new DirectoryCatalog(

                       Path.GetDirectoryName(

                       Assembly.GetExecutingAssembly().Location));

                   compositionContainer = new CompositionContainer(directoryCatalog);

               }

               return compositionContainer;

           }

       }

   }

ข้อมูลโค้ดต่อไปนี้แสดงให้เห็นว่าคุณสามารถดึงอินสแตนซ์ประเภท FileLogger ผ่านคอนเทนเนอร์ได้อย่างไร

FileLogger fileLogger = MEFContainer.Container.GetExportedValue();

ในทำนองเดียวกันในการดึงข้อมูลประเภท DbLogger คุณสามารถใช้ข้อมูลโค้ดต่อไปนี้

DbLogger dbLogger = MEFContainer.Container.GetExportedValue();