Я экспериментирую с 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 добавляется между итерациями цикла, метод Refresh () в DirectoryCatalog выдает исключение ChangeRejectedException, которое объясняется следующим образом:
Состав остается без изменений.
изменения были отклонены из-за
следующие ошибки: Композиция
произвел единственную ошибку композиции.
Основная причина приведена ниже.
Просмотрите CompositionException.Errors
недвижимость для более подробной
информация.
1) Изменения в экспорте предотвращены
не подлежащий возврату импорт
«MEFTest.Program.ProberSet
(ContractName = "ProbeContract.IProbe")»
на части "MEFTest.Program".
Программа находится ниже, следуйте коду для 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();
}
}
}
Плагин. Два других плагина схожи, с той лишь разницей, что они находятся в той же сборке, что и основная программа:
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;
}
}
}