[C#][MEF]Managed Extensibility Framework入門 その1
[C#][MEF]Managed Extensibility Framework入門 その2
その2で簡単なHello worldを作りました。
その3では、このHello worldをちょっと改良して、めんどくさかったクラスのインスタンスをコンテナに登録する部分と、DIコンテナチックに実装との間に一枚インターフェースを挟むようにしてみようと思います。
適当にコンソールアプリケーションを作成して、System.ComponentModel.Composition.dllを参照に追加します。
まず最初に、クラスのインスタンスを登録する部分を改善しようと思います。コンテナがどういう風にクラスのインスタンスを登録していくかを指定するものとして、~Catalogというものがあります。
その中に、System.ComponentModel.Composition.Hosting.AssemblyCatalogというものがあります。これは、指定したアセンブリの中にあるクラス群を自動で登録してくれるかわいい奴です。
ということでMainを、それをつかってコンテナを作成するように書きます。
using System.ComponentModel.Composition.Hosting;
namespace MEFSample2
{
class Program
{
static void Main(string[] args)
{
// アセンブリからクラス登録してね
var catalog = new AssemblyCatalog(typeof(Program).Assembly);
// catalogを使用してコンテナを初期化
var container = new CompositionContainer(catalog);
}
}
}
次に、GreeterとGreeterApp(前のエントリではApplicationって書いてたけどうつのがめんどくさくなったので短いAppにしました)を作成します。
各々、IGreeterとIGreetAppインターフェースと、それを実装するGreeterImplとGreetAppImplクラスがあります。
中身は対して変わりませんが、Export属性とかは、実装クラスのほうにつけて、Export属性の引数にインターフェースの型を指定します。
これでコンテナにIGreeterのインスタンス下さいと、問い合わせるとGreeterImplのインスタンスをくれるようになります。
IGreeterインターフェースとGreeterImplクラス
using System.ComponentModel.Composition;
namespace MEFSample2
{
// 挨拶をする人が実装すべきインターフェース
public interface IGreeter
{
string Greet();
}
// IGreeterの実装 IGreeterインターフェースをキーにしてExportする
[Export(typeof(IGreeter))]
public class GreeterImpl : IGreeter
{
// 単純にHello worldを返す
public string Greet()
{
return "Hello world";
}
}
}
IGreetAppインターフェースとGreetAppImplクラス
using System;
using System.ComponentModel.Composition;
namespace MEFSample2
{
// 挨拶アプリケーションの実装すべきインターフェース
public interface IGreetApp
{
void Run();
}
// IGreetAppの実装 IGreetAppをキーにしてExportする
[Export(typeof(IGreetApp))]
public class GreetAppImpl : IGreetApp
{
// IGreeterをImportする
[Import]
public IGreeter Greeter { get; set; }
public void Run()
{
// ちゃんとGreeterにインスタンスが設定されてれば挨拶が表示されるはず
Console.WriteLine(this.Greeter.Greet());
}
}
}
何処にExportとImportがついてるかがポイントです。
さて、最後に、Mainを実装します。コンテナからIGreetAppのインスタンスを取得してRunメソッドを呼び出します。
using System.ComponentModel.Composition.Hosting;
namespace MEFSample2
{
class Program
{
static void Main(string[] args)
{
// アセンブリからクラス登録してね
var catalog = new AssemblyCatalog(typeof(Program).Assembly);
// catalogを使用してコンテナを初期化
var container = new CompositionContainer(catalog);
// 実行!
var app = container.GetExportedObject<IGreetApp>();
app.Run();
}
}
}
だいぶスッキリしました。