MEF проблема в статье - PullRequest
       3

MEF проблема в статье

0 голосов
/ 24 августа 2011

У меня есть небольшая проблема на этой странице:

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 ]

2 голосов
/ 24 августа 2011

Я думаю, что вы ожидаете, это что-то вроде:

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);
  }
}
0 голосов
/ 25 августа 2011

Пример для объяснения возможности указать интерфейс или абстрактный класс в качестве экспортируемого типа, даже если это то же самое, что и в вашем первом примере.Это отличается от экспорта конкретного типа, как было бы [Export (typeof (EMailSender))]], поскольку ваш импортирующий класс должен знать только контракт, а не настоящее имя класса / классов.Кроме того, он показывает вам способ импортировать все экспортированные типы, реализующие ваш интерфейс, через атрибут ImportMany.Чтобы использовать его в своем коде, сохраняя его как можно более простым, то есть без введения другого уровня импорта или внедрения конструктора, как это было предложено Мэтью (взгляните на 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);
}

Это должно выполнить метод Send всех различных реализаций IMessageSender в вашей сборке.

...