MEF Programming Guide 1.Hosting MEF in an application を試してみた

MEF Programming Guide の上から順に見ていこうと思います。まずは、Hosting MEF in an application からです。


サンプルコードみて、動かしたら雰囲気わかるよね。気になったところを何個か書いてみます。
(最初はざっくり訳を書いてたんだけど、なんかダラダラ長くなったのと間違ってそうなので止めました)


気になった事1

一部抜粋

  private void Compose()
  {
    var container = new CompositionContainer();
    container.ComposeParts(this, new EmailSender());
  }

ここで出てくる ComposeParts メソッドは、CompositionContainer のメソッドではなく、拡張メソッドでSystem.ComponentModel.Composition.AttributedModelServices に定義されているメソッドです。
AttributedModelServices.ComposeParts Method (System.ComponentModel.Composition)
どうも、属性付のオブジェクトから、なんやら色々とコンテナを構成するようです。


気になった事2
インジェクション したいプロパティ に Import 属性 ImportAttribute Class (System.ComponentModel.Composition) を付けて、インジェクションするクラスに Export 属性 ExportAttribute Class (System.ComponentModel.Composition)を付与するみたいです。
MSDN を見ると、ImportAttribute は プロパティ、フィールド、パラメータに付与出来、ExportAttribute は、クラス、メソッド、プロパティ、フィールドに付与出来る となっている。Export をメソッドに付与したらどうなるんだ?と思って試してみた。

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

public class Program
{
  [Import("hoge")]
  public Action<string> method;

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

  public void Run()
  {
    Compose();
    method("aaaa");
    Console.ReadKey();
  }

  private void Compose()
  {
    var catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
    var container = new CompositionContainer(catalog);
    container.ComposeParts(this);
  }
}
public class HogeClass
{
  [Export("hoge")]
  public void HogeHoge(string message)
  {
    Console.WriteLine("hoge" + message);
  }
}

デリゲートに対してインジェクションする際に、メソッドに Export を指定するのかな?


気になった事3
System.ComponentModel.Composition Namespace () を確認すると、Import は ImportAttribute 以外にも、
ImportingConstructorAttribute Class (System.ComponentModel.Composition)ImportManyAttribute Class (System.ComponentModel.Composition) があるみたい。
ImportMany も試してみた。

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

public class Program
{
  [ImportMany]
  private IEnumerable<IMessageSender> _senders;
  
  public static void Main(string[] args)
  {
    Program p = new Program();
    p.Run();
  }

  public void Run()
  {
    Compose();
    foreach (var sender in _senders)
    {
      sender.Send("aaaa");
    }
    Console.ReadKey();
  }

  private void Compose()
  {
    var 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 + " 1");
  }
}
[Export(typeof(IMessageSender))]
public class EmailSender2 : IMessageSender
{
  public void Send(string message)
  {
    Console.WriteLine(message + " 2");
  }
}

ImportMany だと、配列 とか コレクションとかに使えるのかな?



なんか気になった事の方が長くなってしまった。資料を読み進めたら、疑問も解決出来るのかな〜。