前回(以下のエントリー)の実装を改良します。AggregateCatalogクラスでカタログを集約し、一度に読み込めるようにします。
MEFでWPFのプラグインを実装する(複数プラグインをファイル名で指定して読み込む) - プログラマーな日々
プロジェクト構成
- Pluginプロジェクト
クラスライブラリプロジェクトです。プラグインのインターフェースを定義します。前回と同じです。
- HogePluginプロジェクト
WPFユーザーコントロールライブラリプロジェクトです。プラグインの実装クラスを含みます。ビルドしてアセンブリを所定のディレクトリ(D:\@Sandbox\Plugin)に配置します。前回と同じです。
- FugaPluginプロジェクト
WPFユーザーコントロールライブラリプロジェクトです。プラグインの実装クラスを含みます。ビルドしてアセンブリを所定のディレクトリ(D:\@Sandbox\Plugin)に配置します。前回と同じです。
- Mainプロジェクト
WPFアプリケーションプロジェクトです。プラグインを読み込みます。Pluginプロジェクトを参照しますが、HogePluginプロジェクト、FugaPluginプロジェクトは参照しません。AggregateCatalogクラスを使用するように変更します。
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> /// このプロパティにプラグインを読み込みます。privateなプロパティでもOKです。 /// </summary> [ImportMany] private List<IPlugin> Plugins { get; set; } public App() { this.Plugins = new List<IPlugin>(); this.LoadPlugins(); this.Plugins.ForEach(p => p.Execute()); } /// <summary> /// 所定のディレクトリにあるプラグインdllをファイル名を指定して読み込みます。 /// </summary> private void LoadPlugins() { DirectoryCatalog[] catalogs = this.GetDirectoryCatalogs("HogePlugin.dll", "FugaPlugin.dll"); using (AggregateCatalog aggregateCatalog = new AggregateCatalog(catalogs)) using (CompositionContainer container = new CompositionContainer(aggregateCatalog)) { container.SatisfyImportsOnce(this); } } private DirectoryCatalog[] GetDirectoryCatalogs(params string[] fileNames) { DirectoryCatalog[] catalogs = new DirectoryCatalog[fileNames.Length]; for (int i = 0; i < fileNames.Length; i++) { catalogs[i] = new DirectoryCatalog(@"D:\@Sandbox\Plugin", fileNames[i]); } return catalogs; } } }
参考
AggregateCatalog クラス (System.ComponentModel.Composition.Hosting)
ComposablePartCatalog オブジェクトの要素を結合するカタログ。