かずきのBlog@hatena

すきな言語は C# + XAML の組み合わせ。Azure Functions も好き。最近は Go 言語勉強中。日本マイクロソフトで働いていますが、ここに書いていることは個人的なメモなので会社の公式見解ではありません。

Silverlight4でMEFベースのアプリを作るための小さな起動用クラス

Silverlight 4でMEFベースのアプリケーションを作りたいと思ったら、以下のようなクラスを準備するとよさそうです。

using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.ComponentModel.Composition.Hosting;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Primitives;

namespace BootSample
{
    public class Bootstrapper<T>
    {
        [Import]
        public T Shell { get; set; }

        // デフォルトのコンテナを使う
        public Bootstrapper()
        {
        }

        // カタログでコンテナを初期化
        public Bootstrapper(params ComposablePartCatalog[] catalogs)
        {
            CompositionHost.Initialize(catalogs);
        }

        // コンテナを初期化
        public Bootstrapper(CompositionContainer container)
        {
            CompositionHost.Initialize(container);
        }

        public void Run(Application app)
        {
            // Shellを取得して
            CompositionInitializer.SatisfyImports(this);
            // RootVisualに設定する
            app.RootVisual = Shell as UIElement;
        }
    }
}

非常にシンプルなクラスでApplicationのStartupイベント内で使用します。使い方は簡単です。メインにしたいウィンドウにExport属性をつけます。ここでは新規作成したときに作られるMainPageにつけました。

[Export]
public partial class MainPage : UserControl
{
  // 省略
}

Startupイベントの中も非常にシンプルです。

private void Application_Startup(object sender, StartupEventArgs e)
{
    new Bootstrapper<MainPage>().Run(this);
}

MainPage自体がMEFのコンテナから取得されるようになるので、後は、そこを皮切りにしてImportで繋いでやればOKです。カタログで色々初期化したいときは、Bootstrapperを作ってる部分を

new Bootstrapper<MainPage>(
    new AssemblyCatalog(typeof(App).Assembly),
    CreateDeploymentCatalog("SilverlightApplication1.xap"),
    new TypeCatalog(typeof(Hoge)));

private DeploymentCatalog CreateDeploymentCatalog(string path)
{
    var result = new DeploymentCatalog(path);
    result.DonloadAsync();
    return result;
}

みたいにすれば、お好みで色々なクラスをMEFで管理してもらえます。