Arayı çok soğutmadan yeni bir MEF yazısı ile MEF’i biraz daha iyi anlama yönündeki girişimlerimiz sürüyor.Sürecekte…Önceki yazılarımda MEF ile ilgili örnekler vererek, az biraz MEF’in ne olduğunu çözmeye yaklaşmıştık hatırlarsanız.Tekrar göz atmak gerekirse;

  1. MEF ile esneklik kazanıyoruz…
  2. MEF’de “Part”lara kendi “metadata” bilgilerimizi nasıl ekleriz acaba?
  3. MEF’i basit bir WPF uygulaması ile daha iyi anlıyoruz…

Bu sefer de MEF’in bir den fazla “Part”ı, kendi tabirimiz ile “plugin”lerimizi nasıl canlandırdığını ve metodlarını nasıl çağırabileceğimizi anlatmaya çalışacağım. Ve önceki yazılarda ki gibi, kod yazıyoruz…Yaşasın kod yazmak… 🙂

Önceki yazılardan hatırlarsanız işe yaramayan bir IPlugin arayüzümüz vardı…Bu işe yaramayan arayüzümüzü biraz daha anlamlı kılarak bir metod eklemek ile başlayalım önce. Bu metodu ekleyerek, bu arayüzden türeyen her “Part”ın(yani plugin’nin) bu metodu tanımlamasını zorunlu hale getiriyoruz.

    public interface IPlugin
    {
        //Bu arayüzü kullana nesneler
        //bu metod ile kendi içindeki
        //bir değeri dışarı versin...
        string GetPrivateData();
    }

Bu arayüzümdeki değişikliği önceki yazılardan aşina olduğumuz FirstWPFPlugin projesine de yansıtıyoruz.

public partial class FirstWPFPlugin : UserControl,IPlugin
    {
        //İçerde gizlediğimiz gereksiz bir değer
        private string _xValue = "";
        public FirstWPFPlugin()
        {
            InitializeComponent();
            _xValue = "Birinci plugin içinde ki private X değişkeninin değeri";
        }

        //Sanırım fazla açıklamaya gerek yok (:
        private void button1_Click(object sender, RoutedEventArgs e)
        {
            MessageBox.Show("Hello world");
        }

        //IPlugin arayüzünden gelen metodumuz...
        public string GetPrivateData()
        {
            return _xValue;
        }
    }

Bu şekilde FirstWPFPlugin’miz artık GetPrivateData metodu ile kendi içindeki bir değişkeni dışarı veriyor. Şu ana kadar bir şey yok…Şimdi MEF tarafına geçelim…Öncelikle ilk yazımdaki “Import” kavramını hatırlamakta fayda var. IPlugin arayüzü ile “Export” ettiğimiz “Part”ları, PluginFactory sınıfımız ile “Import” ediyor olacağız. Bu sayede arayüzümüz bize sağladığı metodları, ana uygulamamızda kullanabileceğiniz. Bu arayüzden türeyen bir çok plugin olabileceğinden, arayüzün metodu her plugin için farklılık gösterebilecektir.

Burda önemli olan bir diğer noktada ana uygulamamıza birden fazla plugin yükleyebiliyor olabilmemiz. Bunun için “ImportMany” özelliğini kullanıyor olacağız. Bunun için PluginFactory sınıfımızda aşağıdaki gibi bir değişken tanımlamamız gerekmekte.

    public class PluginFactory
    {

        //ImportMany özelliği ile IPlugin arayüzünden türeyen ve
        //"PluginForWPF" şeklinde belli bir kontrat ile tanımladığımız
        //plugin(Part)'ları yükleyebileceğimizi belirtiyoruz.
        //IEnumerable tipinde olması, birden fazla plugin olabileceği
        //için gerekli...
        [ImportMany("PluginForWPF", typeof(IPlugin))]
        IEnumerable<Lazy<IPlugin, IPluginMetaData>> Plugins;
        .
        .
        .
        .

Şimdi PluginFactory sınıfımızda yazacağımız bir metod ile IPlugin arayüzünden türeyen “Part”larımızı, ya da kendi tanımlamamız ile plugin’lerimizi bu “Plugins” değişkenine atamamız lazım…Bunun için de aşağıdaki gibi bir kod şimdilik işimizi görecektir.

        //Kullanıcı arayüzümüzden çağıracağımız bu metod ile "Plugins"
        //değişkeninin yaratıyoruz.
        public string ExecutePluginMethod(string pluginName)
        {
            //Önceki yazılarda container nesnesini, PluginFactory
            //sınıfımızı yaratırken yaratmıştık hatırlarsanız.
            //container'ımızın, ComposeParts() metodu ile,
            //PluginFactory sınıfının içindeki Import özelliği olan
            //değişkenleri yaratıyoruz. this parametresi PluginFactory
            //nesnesini belirtiyor.
            container.ComposeParts(this);

            //Birden fazla plugin yani "Part" olabileceği için,
            //hangi plugin'nin metodunu çalıştırmak için LINQ ile
            //yüklenen plugin'lerin metadata'larını sorgulayarak,
            //parametrede gelen plugin ismi ile istediğimiz plugin'i
            //alıyoruz.
            IPlugin s = (IPlugin)Plugins.Where(e => e.Metadata.Name == pluginName).FirstOrDefault().Value;

            //Ve daha sonra IPlugin arayüzümüzün istediğimiz metodunu çalıştırıyoruz.
            return s.GetPrivateData();
        }

Artık ana uygulamamıza yüklenen “plugin”lerin istediğimiz metodlarını çalıştırabiliriz. Benzer bir şekilde bir çok metodu çalıştırmak artık sizin elinizde…Şimdilik bu kadar…Bir sonraki MEF yazısında tüm bu örneklerdeki kavramları daha iyi anlıyor olacağız.Çok pratik yaptık, biraz da teoriye inelim değil mi…(:

Not: Bu yazıda geçen proje örneğini buradan indirebilirsiniz.