文章中的MEF问题

时间:2011-08-24 13:19:58

标签: .net mef

我在这个页面有一点问题:

http://mef.codeplex.com/wikipage?title=Parts&referringTitle=Guide

我有这个程序:

using System.ComponentModel.Composition;
  using System.ComponentModel.Composition.Hosting;
  using System.Reflection;
  using System;

  public class Program
  {
    [Import]
    public IMessageSender MessageSender { get; set; }

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

    public void Run()
    {
      Compose();
      MessageSender.Send("Message Sent");
    }

    private void Compose()
    {
      AssemblyCatalog catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
      var container = new CompositionContainer(catalog);
      container.ComposeParts(this);
    }
  }

  public interface IMessageSender
  {
    void Send(string message);
  }

  [Export(typeof(IMessageSender))]
  public class EmailSender : IMessageSender
  {
    public void Send(string message)
    {
      Console.WriteLine(message);
    }
  }

我不明白我如何编辑它以使用此代码:

  [Export(typeof(IMessageSender))]
  public class EmailSender : IMessageSender {
    ...
  }

  [Export(typeof(IMessageSender))]  
  public class TCPSender : IMessageSender {
    ...
  }

  public class Notifier {
    [ImportMany]
    public IEnumerable<IMessageSender> Senders {get; set;}
    public void Notify(string message) {
      foreach(IMessageSender sender in Senders) 
        sender.Send(message);
    } 
  }

2 个答案:

答案 0 :(得分:2)

我认为你期待的是:

public interface INotifier
{
  void Notify(string message);
}

[Export(typeof(INotifier))]
public class Notifier : INotifier
{
  [ImportMany]
  public IEnumerable<IMessageSender> Senders { get; set; }

  public void Notify(string message)
  {
    foreach (var sender in Senders)
      sender.Send(message);
  }
}

您可以[Import] INotifier的实例:

[Import]
public INotifier Notifier { get; set; }

虽然,我更喜欢构造函数注入,因为它更好地表达了类的依赖关系:

[Export(typeof(INotifier))]
public class Notifier : INotifier
{
  private readonly IEnumerable<IMessageSender> _senders;

  [ImportingConstructor]
  public Notifier(IEnumerable<IMessageSender> senders)
  {      
    _senders = senders;
  }

  public void Notify(string message)
  {
    foreach (var sender in _senders)
      sender.Send(message);
  }
}

答案 1 :(得分:0)

该示例用于解释将接口或抽象类指定为导出类型的可能性,即使这是在第一个示例中完成的操作也是如此。这与导出具体类型不同,例如[Export(typeof(EMailSender))]可能已经完成,因为您的导入类必须只知道契约,而不是类/类的真实名称。此外,它还显示了通过ImportMany属性导入实现接口的所有导出类型的方法。要在代码中使用它,使其保持尽可能简单,即不引入Matthew建议的其他导入级别或构造函数注入(请查看http://mef.codeplex.com/wikipage?title=Declaring%20Imports&referringTitle=Guide),您只需在Program类中修改这些方法:

public void Run()
{
  Notifier nfr = new Notifier();
  Compose(nfr);
  nfr.Notify("Message Sent");
}

private void Compose(Notifier nfr)
{
  AssemblyCatalog catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
  var container = new CompositionContainer(catalog);
  container.ComposeParts(nfr);
}

这应该在程序集中执行IMessageSender的所有不同实现的Send方法。