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)非公开组合将不被支持。
 
posted @ 2014-04-17 15:28  安布雷拉  阅读(1068)  评论(0编辑  收藏  举报