我到目前为止使用MEF的最大问题是,当我在插件加载器包装器中编写部件时,在找到其中一个程序集的导入解决问题时完全加载。理想情况下,我希望ComposeParts能够展示某种“忽略和继续”行为,因为理想的用户体验需要加载尽可能多的插件,并且只需在特定插件无法加载时记录事件。我无法在任何地方的文档中找到有关此内容的信息。
如果您对如何解决这个问题有任何其他建议,我正在听!
答案 0 :(得分:10)
Wim的例子有基本的想法,但不是直接拉动容器,我建议你做一个像这样的Lazy ImportMany:
[Export]
public class MyApplication
{
[ImportMany(typeof(IPlugin))]
public IEnumerable<Lazy<IPlugin>> Plugins { get; set; }
}
然后你可以逐个初始化插件并从中捕获任何错误,如:
void InitializePlugins()
{
foreach (Lazy<IPlugin> plugin in Plugins)
{
try
{
plugin.Value.Initialize();
}
catch (CompositionException e)
{
// Handle the error accordingly
}
}
}
实际的插件在你开启之前不会被创建.Value第一次,如果插件在导入的构造函数或属性设置器中有错误,则会发生错误。另请注意,我抓住了CompositionException,如果插件出错了,这将是.Value调用的内容。
答案 1 :(得分:2)
您可以使用AllowDefault
参数。如果没有可用的部分可以满足导入,则在导入时将其设置为true将导致依赖性为null
。
public class MyComponent
{
[Import(AllowDefault=true)]
public IMyDependency MyDependency { get; set; }
}
要加载所有可用插件但忽略因缺少部件而无法加载的插件,[ImportMany]
默认情况下已经执行了您想要的操作:
[Export]
public class MyApplication
{
[ImportMany(typeof(IPlugin))]
public IEnumerable<IPlugin> Plugins { get; set; }
}
请注意,上述技术只能消除因缺少部件而导致的合成错误。如果某个部件及其导入实际可用,但在调用构造函数时会抛出意外的异常,那么您仍会得到异常。要忽略与组合无关的问题,可以直接调用容器:
IEnumerable<IPlugin> GetPluginsFromContainer(CompositionContainer container)
{
foreach (Lazy<IPlugin> pluginExport in container.GetExports<IPlugin>())
{
try
{
yield return pluginExport.Value;
}
catch (Exception e)
{
// report failure to instantiate plugin somewhere
}
}
}