MEF系列三:声明导出(Exports)

时间:2021-11-24 23:18:09

组合部件声明导出通过 [System.ComponentModel.Composition.ExportAttribute]属性。在MEF中有几种不同的方法通过属性和方法去声明导出包括部件级别

组合部件导出

组合部件级别导出用于 当组合部件需要导出它本身时,为了组合部件导出它本身,简单用[System.ComponentModel.Composition.ExportAttribute] 修饰组合部件如下面的代码片断
[Export]
public class SomeComposablePart {
  ...
}

属性导出

部件还可以导出属性,几个原因说明属性导出是有益的
  • 它们允许导出封闭类型如CLR核心类型,或者其它第三方部件类型
  • 它们允许解耦部件跟部件之间的创建,例如导出运行时创建的HttpContext
  • 它们允许在相同的家庭相关的导出组合部分,如DefaultSendersRegistry可组合部分导出一个默认设置senders的属性
例如在下面的例子中你可能拥有一个导出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; }
  }

方法导出

方法导出就是对象其中的一个方法导出。 Methods are exported as delegates which are specified in the Export contract. 方法导出包括以下几个好处
  • 导出允许更细颗粒度控制,例如,规则引擎可以导入一套插入式方法导出。
  • 避免了调用者对类型的任何认识
  • They can be generated through light code gen, which you cannot do with the other exports.
注:方法导出可能没有超过4参数由于框架的限制

在下面的例子中,MessageSender类导出它的Send方法作为代理Action<string>,程序引进一样的代理。
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");
    }
  }

你也能能过一个简单的契约导出方法,如下面例子,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");
    }
  }
注:当你导出方法时,你需要提供类型或字符串作为契约名称,不能让它空白

继承导出

MEF为提供通过基类/接口定义导出让实现者 自动继承的能力。这是典型的想利用MEF和遗留的框架进行集成又不需要修改原有的客户端代码,为了系统提供此功能需要使用System.ComponentModel.Composition.InheritedExportAttribute例如下面ILogger有一个InheritedExport Logger实现了ILogger
[InheritedExport]
public interface ILogger {
  void Log(string message);
}

public class Logger : ILogger {
  public void Log(string message);
}

发现非公共组合部件

MEF支持发现公共和非公共部件。这种行为不需要你做任何事,请注意在媒介和部分信任环境(包括Silverlight)非公共部分将不支持。
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.Reflection;
using System;

public class Program
{
public static void Main(string[] args)
{
Program p = new Program();
p.Run();
}

public CompositionContainer container = null;

/// <summary>
/// Set the container global variable
/// </summary>
private void Compose()
{
AssemblyCatalog catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());

container = new CompositionContainer(catalog);
}

public void Run()
{
Compose();

// Calling a method without use interfaces. More flexible and "easy to use".
// Useful for plugins
foreach (var view in container.GetExports<Func<string, bool>>("MessageSender"))
{
Console.WriteLine(view.Value("PUC-Campinas"));
}

Console.ReadKey();
}


}

public class MessageSender
{
[Export("MessageSender")]
public bool Send(string message)
{
Console.WriteLine(message);
return true;
}
}


注:以上只是为了方便我自己学习记录,有些地方翻译不到位,唯恐误导读者,如有需要请阅读原文
http://mef.codeplex.com/wikipage?title=Declaring%20Exports&referringTitle=Guide