プログラマーな日々

プログラマーをやっています。好きなものは、C#, TaskChute Cloud, WorkFlowy, Backlog, AWSです。

MEFでWPFのプラグインを実装する(複数プラグイン編)

前回(以下のエントリー)の実装を改良して複数のプラグインを読み込んでみます。
MEFでWPFのプラグインを実装する - プログラマーな日々
MEFは.NET4で提供された.NET標準のDIコンテナです。このMEFを使ってWPFのプラグインを実装してみます。

アプリ実行

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

プロジェクト構成

  • Pluginプロジェクト

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

  • HogePluginプロジェクト

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

  • FugaPluginプロジェクト

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

  • Mainプロジェクト

WPFアプリケーションプロジェクトです。プラグインを読み込みます。Pluginプロジェクトを参照しますが、HogePluginプロジェクト、FugaPluginプロジェクトは参照しません。複数プラグインを読み込むように変更します。

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();        
        }
    }
}

FugaPluginプロジェクト

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

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

        void IPlugin.Execute() {
            this.Title = "Hello World, Fuga";
            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>
        /// ImportMany属性を指定するとこのプロパティに複数のプラグインが読み込まれます。privateなプロパティでもOKです。
        /// </summary>
        [ImportMany]
        private List<IPlugin> Plugins { get; set; }

        public App() {
            this.Plugins = new List<IPlugin>();
            this.LoadPlugin();
            this.Plugins.ForEach(p => p.Execute());
        }

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