Импорт детали из другой сборки - PullRequest
1 голос
/ 29 ноября 2011

Подход

Я использую MEF для создания подключаемого модуля, если хотите, приложения.У моего MEF-хоста ILogger, который выставляет TraceMessage(string message).Класс Logger реализует ILogger и имеет атрибут Export, поэтому Logger выглядит следующим образом:

[Export(typeof (ILogger))]
public class Logger : ILogger
{ }

Идея состоит в том, что различным плагинам может быть предложен центральный регистратор, который они могут записатьк.Таким образом, создание экземпляра будет происходить с помощью атрибута [Import], например:

[Export(typeof (ILogger))]
public class Logger : ILogger
{
    private readonly IWindsorContainer _container;

    public ICloudTrace CloudTrace
    {
        get { return _container.Resolve<ICloudTrace>(); }
    }

    public Logger()
    {
        _container = new WindsorContainer(new XmlInterpreter());
    }

    public void TraceMessage(string categoryName, string componentName, string message)
    {
        CloudTrace.TraceMessage(categoryName, componentName, message);
    }
}

И впоследствии сообщение журнала будет записано с помощью Logger.TraceMessage(string message).

Задача

Однако этот подход выдает InvalidOperationException на моем хосте, когда он пытается разрешить экспорт, с сообщением об ошибке Sequence contains no matching element.

Экспорт разрешается в ResolveType(string commandType) (где commandType - параметр командной строки, необходимый для запуска соответствующего плагина).ResolveType() выглядит следующим образом:

public dynamic ResolveType(string commandType)
{
   try
   {
     return this.Container.GetExports<ICommand, ICommandMetaData>()
                .First(contract => contract.Metadata.CommandType.Equals(commandType, StringComparison.OrdinalIgnoreCase))
                .Value;
    }
    catch (Exception e)
    {
       Console.WriteLine(e.message);
    }
}

Следует отметить, что каждый плагин имеет Execute(Dictionary<string, string> parameters), который является точкой входа для плагина, а класс, содержащий этот метод, украшен [Export(typeof(ICommand))] [ExportMetadata("CommandType","CommandLine Command string goes here")] атрибутами.

1 Ответ

0 голосов
/ 30 ноября 2011

Проблема была в конструкции CompositionContainer. В настоящее время он просто загружает сборку плагина, указанную в командной строке, вместо сканирования каталога или загрузки выполняющейся в данный момент сборки. Это было сделано по разным причинам. Итак:

var assemblyCatalog = new AssemblyCatalog(Assembly.LoadFrom(assemblyFile: assemblyToLoad));

где assemblyToLoad - это строка в DLL-файл для определенного плагина. Однако регистратор находится в хосте, поэтому сборка хоста должна быть загружена. Таким образом:

var assemblyCatalog = new AggregateCatalog(new AssemblyCatalog(Assembly.GetExecutingAssembly()),
                                           new AssemblyCatalog(Assembly.LoadFrom(assemblyFile: assemblyToLoad)));

исправляет проблему. Спасибо @Matthew Abbott за указание на это

...