私はMEFを実験していて、次のような特定のインターフェイスを実装する「プラグイン」を呼び出すテストプログラムを作成しました。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ProbeContract
{
public interface IProbe
{
int DoProbe(string what);
List<string> GetCapabilities();
}
}
独自のアセンブリから、および見つかった場合は追加のDLLを配置するディレクトリから「プラグイン」をロードするサンプルコンソールプログラムを作成しました。プラグインディレクトリが空であるか(「ネイティブ」プラグインのみが呼び出される)、または互換性のあるDLLがあるかどうかに関係なく、プログラムは正常に動作します。しかし...ループの反復の間に新しいDLLが追加されると、DirectoryCatalogのRefresh()メソッドはChangeRejectedExceptionをスローします。これは、次のように説明されます。
構成は変更されません。次のエラーのため、変更は拒否されました。コンポジションで単一のコンポジションエラーが発生しました。根本的な原因を以下に示します。詳細については、CompositionException.Errorsプロパティを確認してください。
1)パーツ「MEFTest.Program」の再構成不可能なインポート「MEFTest.Program.ProberSet(ContractName = "ProbeContract.IProbe")」によって防止されたエクスポートの変更。
プログラムは以下のとおりです。追加しようとしているDLLのコードが続きます。私は何が間違っているのですか?
using System;
using System.IO;
using System.Reflection;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ProbeContract;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
namespace MEFTest
{
class Program
{
[ImportMany]
IEnumerable<IProbe> ProberSet { get; set; }
CompositionContainer exportContainer;
DirectoryCatalog pluginCatalog;
AggregateCatalog catalog;
private void Run()
{
catalog = new AggregateCatalog();
catalog.Catalogs.Add(new AssemblyCatalog(Assembly.GetExecutingAssembly()));
string myExecName = Assembly.GetExecutingAssembly().Location;
string myPath = Path.GetDirectoryName(myExecName);
pluginCatalog = new DirectoryCatalog(myPath + "/Plugins");
catalog.Catalogs.Add(pluginCatalog);
exportContainer = new CompositionContainer(catalog);
CompositionBatch compBatch = new CompositionBatch();
compBatch.AddPart(this);
compBatch.AddPart(catalog);
exportContainer.Compose(compBatch);
for (; ; )
{
Console.Write("Press any key to run all probes: ");
Console.ReadKey(true);
Console.WriteLine();
pluginCatalog.Refresh();
foreach (var Prober in ProberSet)
{
Prober.DoProbe("gizmo");
}
}
}
static void Main(string[] args)
{
Program p = new Program();
p.Run();
}
}
}
プラグイン。他の2つのプラグインは類似していますが、唯一の違いは、メインプログラムと同じアセンブリに存在することです。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel.Composition;
using ProbeContract;
namespace OtherProbes
{
[Export(typeof(IProbe))]
public class SpankyNewProber : IProbe
{
public int DoProbe(string what)
{
Console.WriteLine("I'm Spanky and New and I'm probing [{0}]", what);
return 0;
}
public List<string> GetCapabilities()
{
List<string> retVal = new List<string>();
retVal.Add("spanky");
retVal.Add("new");
return retVal;
}
}
}