从其他部件导入零件
本文关键字:零件 导入 其他部 | 更新日期: 2023-09-27 18:16:18
方法
我正在使用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")]
属性进行装饰。
问题出现在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指出这一点