Architect's Log

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

MEFでWPFのプラグインを実装する(複数プラグインをファイル名で指定して読み込む)

前回(以下のエントリー)の実装を改良して、ファイル名を指定して複数のプラグインを読み込めるようにします。
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 {
        private List<IPlugin> Plugins;

        /// <summary>
        /// このプロパティにプラグインを読み込みます。privateなプロパティでもOKです。
        /// </summary>
        [Import]
        private IPlugin Plugin {
            set { Plugins.Add(value); }
        }

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

        /// <summary>
        /// 所定のディレクトリにあるプラグインdllをファイル名を指定して読み込みます。
        /// </summary>
         private void LoadPlugins() {
            this.LoadPlugin("HogePlugin.dll");
            this.LoadPlugin("FugaPlugin.dll");
        }

        private void LoadPlugin(string fileName) {
            using (DirectoryCatalog catalog
                = new DirectoryCatalog(@"D:\@Sandbox\Plugin", fileName))
            using (CompositionContainer container = new CompositionContainer(catalog)) {
                container.SatisfyImportsOnce(this);
            }
        }
    }
}

LoadPluginがいまいちですね。複数ファイルをもっとスマートに読み込む方法はあるのかな?