Architect's Log

I'm a Cloud Architect. I'm highly motivated to reduce toils with driving DevOps.

MEFでWPFのプラグインを実装する

MEFは.NET4で提供された.NET標準のDIコンテナです。このMEFを使ってWPFのプラグインを実装してみます。

アプリ実行

プラグインのメソッドが呼ばれ、ウィンドウが表示されます。

プロジェクト構成

  • Pluginプロジェクト

クラスライブラリプロジェクトです。プラグインのインターフェースを定義します。

  • HogePluginプロジェクト

WPFユーザーコントロールライブラリプロジェクトです。プラグインの実装クラスを含みます。ビルドしてアセンブリを所定のディレクトリ(D:\@Sandbox\Plugin)に配置します。

  • Mainプロジェクト

WPFアプリケーションプロジェクトです。プラグインを読み込みます。Pluginプロジェクトを参照しますが、HogePluginプロジェクトは参照しません

Pluginプロジェクト

IPlugin.cs
namespace Plugin {
    public interface IPlugin {
        void Execute();
    }
}

HogePluginプロジェクト

HogeWindow.xaml
<Window x:Class="HogePlugin.HogeWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="HogeWindow" Height="100" Width="300">
</Window>
HogeWindow.xaml.cs
using System.ComponentModel.Composition;
using System.Windows;
using Plugin;

namespace HogePlugin {
    /// <summary>
    /// 型を指定してExport属性を指定します。
    /// </summary>
    [Export(typeof(IPlugin))]
    public partial class HogeWindow : Window, IPlugin {
        public HogeWindow() {
            InitializeComponent();
        }

        void IPlugin.Execute() {
            this.Title = "Hello World, Hoge";
            this.Show();        
        }
    }
}

Mainプロジェクト

App.xaml
<Application x:Class="Main.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
</Application>
App.xaml.cs
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.Windows;
using Plugin;

namespace Main {
    public partial class App : Application {
        /// <summary>
        /// Import属性を指定するとこのプロパティにプラグインが読み込まれます。privateでもOKです。
        /// </summary>
        [Import]
        private IPlugin Plugin { get; set; }

        public App() {
            this.LoadPlugin();
            this.Plugin.Execute();
        }

        /// <summary>
        /// 所定のディレクトリにあるプラグインdllファイルを読み込みます。
        /// </summary>
        private void LoadPlugin() {
            using (DirectoryCatalog catalog
                = new DirectoryCatalog(@"D:\@Sandbox\Plugin", "HogePlugin.dll"))
            using (CompositionContainer container = new CompositionContainer(catalog)) {
                container.SatisfyImportsOnce(this);
            }
        }
    }
}

参考

Blog

MEF(Managed Extensibility Framework) - あおきのTechメモ
MicrosoftによるDIコンテナのような拡張フレームワークのようなMEF。 ...

はじめてのMEF - 匣の向こう側 - あまりに.NETな

MEF(Managed Extensibility Framework)はちょっと変わったDIコンテナ - Architect Life
で、軽く触ってみたんだけど、これって要はDIコンテナなのね。他のDIコンテナよりも少しだけスコープが広いみたいな。 ...

青柳 臣一 ブログ(技術系): [Silverlight] MEF を使って XAP を動的に読み込む その1
前の記事で Silverlight 4 では MEF (Managed Extensibility Framework) を使って XAP を動的に読み込めばいいんじゃないかと書きましたが、せっかくなのでサンプルを紹介しときます。 ...

Googleソースコード検索

2014/1/13追記 Googleソースコード検索のサービスは終了しました。

MSDNマガジン

Managed Extensibility Framework - Managed Extensibility Framework による .NET 4 で構成可能なアプリケーションの構築
まもなくリリースされる Microsoft .NET Framework 4 では、新たにアプリケーションの開発が大幅に容易になる魅力的なテクノロジが登場します。アプリケーションを設計する際にメンテナンスや機能拡張が容易になるようにと頭を悩ませたことのある方は、ぜひお読みください。 ...

MSDN マガジン: Cutting Edge - アプリケーションの拡張: MEF と IoC の違い
「アプリケーションを構成するあらゆる部分を実行時に検出できる、拡張可能なアプリケーションを作成する方法はあるだろうか」というのは、終わることのない質問ですが、Microsoft .NET Framework 4 には、この問いに適切な答えを提供するために設計された新しいコンポーネントがあります。 ...

MSDNライブラリ

DirectoryCatalog クラス (System.ComponentModel.Composition.Hosting)
指定されたディレクトリのアセンブリ内で属性付きパーツを探索します。 ...

CompositionContainer クラス (System.ComponentModel.Composition.Hosting)
パーツの合成を管理します。 ...

CompositionContainer.SatisfyImportsOnce メソッド (System.ComponentModel.Composition.Hosting)
指定した ComposablePart オブジェクトのインポートを、再合成の対象としては登録せずに満たします。 ...