MEF 編程指南(三):聲明導出

組合部件經過  [System.ComponentModel.Composition.ExportAttribute] 特性聲明導出。MEF 有幾種不一樣的方式聲明導出,包括在部件層面(Part Level),經過屬性(Properties)和方法(Method)聲明導出。
 
 
組合部件導出(Composable Part Exports)
 
 
當組合部件須要導出自身時候使用組合部件層面導出。爲了組合部件導出自身,以下例代碼所示,僅僅利用 [System.ComponentModel.Composition.ExportAttribute] 特性標識組合部件。
 
    public class SomeComposablePart { }
 
 
屬性導出(Property Exports)
 
部件也可導出屬性。屬性導出的優點有幾點緣由。
 
 
  • 容許導出密封類(Sealed Types),好比:核心 CLR 類型,或者其餘三方類型。
  • 容許如何建立導出中解耦。好比:導出運行時(Runtime)爲你建立存在的 HttpContext。
  • 容許相同的組合部件擁有繼承關係的導出,好比:DefaultSendersRegistry 組合部件導出默認的一組 Sender 做爲屬性。
 
 
以下例:可能有一個配置類(Configuration Class)導出一個整形(Integer)的「TImeout」契約。
 
    public class Configuration
    {
        [Export("Timeout")]
        public int Timeout
        {
            get { return int.Parse(ConfigurationManager.AppSettings["Timeout"]); }
        }
    }
 
    [Export]
    public class UsesTimeout
    {
        [Import("Timeout")]
        public int Timeout { get; set; }
 
        public UsesTimeout()
        {
            Compose();
        }
 
        private void Compose()
        {
            //var container = new CompositionContainer();
            //container.ComposeParts(this, new EmailSender());
            AssemblyCatalog catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
            var container = new CompositionContainer(catalog);
            container.ComposeParts(this);
        }
    }

 

 
 
方法導出(Method Exports)
 
方法導出是指部件導出其中一個方法。方法指定爲導出契約,做爲委託(Delegates)被導出。方法導出包括下面的許多優點。
 
 
 
  • 容許更細力度的控制導出什麼。好比:規則引擎(Rules Engine)可能導入一組可插拔(Pluggable)的方法導出。
  • 規避了調用者對類型的認知狀況。
  • 能夠經過 Light Code Gen 生成,which you cannot do with the other exports。
 
注意:因爲框架限制,方法導出不能超出4個參數。

下面的例子中,MessageSender 類的 Send 方法做爲 Action<string> 委託導出。Processor 類導入一樣的委託。
 
    public class MessageSender
    {
        [Export(typeof(Action<string>))]
        public void Send(string message)
        {
            Console.WriteLine(message);
        }
    }
 
    [Export]
    public class Processor
    {
        [Import(typeof(Action<string>))]
        public Action<string> MessageSender { get; set; }
 
        public void Send()
        {
            MessageSender("Processed");
        }
 
        public Processor()
        {
            Compose();
        }
 
        private void Compose()
        {
            //var container = new CompositionContainer();
            //container.ComposeParts(this, new EmailSender());
            AssemblyCatalog catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
            var container = new CompositionContainer(catalog);
            container.ComposeParts(this);
        }
    }

 

 
 
你也可使用簡單字符約束(Simple String Contract)導出導入方法。例如:下面的「Sender」約束的使用。
 
    public class MessageSender
    {
        [Export("MessageSender")]
        public void Send(string message)
        {
            Console.WriteLine(message);
        }
    }
 
    [Export]
    public class Processor
    {
        [Import("MessageSender")]
        public Action<string> MessageSender { get; set; }
 
        public void Send()
        {
            MessageSender("Processed");
        }
 
        public Processor()
        {
            Compose();
        }
 
        private void Compose()
        {
            //var container = new CompositionContainer();
            //container.ComposeParts(this, new EmailSender());
            AssemblyCatalog catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
            var container = new CompositionContainer(catalog);
            container.ComposeParts(this);
        }
    }

 

 
注意:當作方法導出時,必須提供類型或者字符約束名,而不能留空。
 
繼承導出
 
MEF 支持基類/接口定義導出,由實現者自動繼承的能力。利用 MEF 和遺留框架集成,可是又不想修改現有的客戶代碼,這是理想的。System.ComponentModel.Composition.InheritedExportAttribute 特性提供這種能力。例如:ILogger 標識了繼承導出的特性。Logger 實現了 ILogger,所以自動實現了 ILogger 的導出。
 
    [InheritedExport]
    public interface ILogger
    {
        void Log(string message);
    }
 
    public class Logger : ILogger
    {
        public void Log(string message) { }
    }
 
 
發現非公開(Non-Public)組合部件
 
MEF 支持發現公開和非公開的部件。你無須爲了這種用法作任何事情。請注意:在 medium/partial trust 環境(包括 Sliverlight)非公開組合將不被支持。
 
相關文章
相關標籤/搜索