Подход
Я использую 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")]
атрибутами.