开发者

MEF problem in article

I have a little problem in this page:

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

I have this program:

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);
    }
  }

And i don't understand how i can edit it to use with this code:

  [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);
    } 
  }开发者_如何学Python


I think what you are expecting, is something like:

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);
  }
}

Whereby, you can [Import] an instance of INotifier:

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

Although, I do prefer constructor injection, as it better expresses dependencies for your class:

[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);
  }
}


The example is there to explain the possibility to specify an interface or an abstract class as the exported type, even if this is something that is done in your first example, too. This is different from exporting a concrete type, like [Export(typeof(EMailSender))] would have done, since your importing class must know only the contract, not the real name of the class/classes. Furthermore it shows you the way to import all the exported types implementing your interface, through the ImportMany attribute. To use it in your code keeping it as simple as possible, i.e. without introducing another import level or constructor injection as suggested by Matthew (take a look at http://mef.codeplex.com/wikipage?title=Declaring%20Imports&referringTitle=Guide) you could simply modify these methods in your Program class:

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);
}

This should execute the Send method of all the different implementation of IMessageSender in your assembly.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜