はじめてのMEF

CodePlex Archive

The Managed Extensibility Framework (MEF) is a new library in .NET that enables greater reuse of applications and components.

とありますが、とりあえずDIコンテナと考えておけばOK。既に記事として取り上げたつもりでしたが、過去に紹介していたのは、
はじめてのUnity - 匣の向こう側 - あまりに.NETな
Unityでした。あと、Monologueの方でMEFのライセンスがMS-LPLなので云々とかあった記憶がありますが、これについては改善される方向なようです。


では、簡単なサンプルでMEFを見てみましょう。

まずは、インタフェースの定義。いつものIGreeting。

public interface IGreeting
{
    void Say(string msg);
}

次に実装クラス。

using System.ComponentModel.Composition;

[Export(typeof(IGreeting))]
public class GreetingImpl : IGreeting
{
    public void Say(string msg)
    {
        System.Console.WriteLine ("[{0}]", msg);
    }
}

注目する箇所は、

[Export(typeof(IGreeting))]
public class GreetingImpl : IGreeting

で、Export属性を付けることで公開されます。

最後にインジェクション。ここではsetterインジェクションを使います。

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

public class Host
{
    [Import]
    public IGreeting Greeting { get; set; }

    public void Run()
    {
        Greeting.Say("Hello");
    }

    public static void Main()
    {
        var host = new Host();
        var catalog = new DirectoryPartCatalog();
        var container = new CompositionContainer(catalog.CreateResolver());
        container.AddPart(host);
        container.Compose();
        host.Run();
    }
}

ここでも注目は、

    [Import]
    public IGreeting Greeting { get; set; }

Import属性を付けることでExport属性が付いている同一の型の実装クラスがインジェクションされます。ちなみに今回のサンプルは、

  • IGreeting.dll
  • GreetingImpl.dll
  • Host.exe

これら3つのアセンブリから出来ており、Host.exeはIGreeting.dllを参照していますが、GreetingImpl.dllは参照していません。するとどうやってGreetingImpl.dllを見つけてくるのでしょうか?

実は、

        var catalog = new DirectoryPartCatalog();

このDirectoryPartCatalogがミソで、このカタログを使うことによって指定したディレクトリ内のアセンブリを検索対象にするのでした。ちなみに今回は引数無しのコンストラクタを呼んでいるのでカレントディレクトリが対象になります。MEFでは、このようなカタログが複数存在し、対象アセンブリの探し方を色々選択することが出来ます。

MEFをちょっと弄ってみた感想としては、結構使いやすそうな感じで期待です。


(余談)
ライセンスの件の記事に代替としてMono.Addinsが紹介されていたので、DIコンテナ的に使えるモノなのかとMono.Addionsを調査していたのですが、アドインシステムという括りではDIコンテナと重なる部分もありましたが、よりプリミティブなライブラリのようで、ちょっと求めるモノと違いました。