MEF的CompositionContainer.ComposeParts - 加载可以解决的任何内容,并忽略错误

时间:2010-06-04 13:05:05

标签: .net plugins inversion-of-control mef

我到目前为止使用MEF的最大问题是,当我在插件加载器包装器中编写部件时,在找到其中一个程序集的导入解决问题时完全加载。理想情况下,我希望ComposeParts能够展示某种“忽略和继续”行为,因为理想的用户体验需要加载尽可能多的插件,并且只需在特定插件无法加载时记录事件。我无法在任何地方的文档中找到有关此内容的信息。

如果您对如何解决这个问题有任何其他建议,我正在听!

2 个答案:

答案 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
       }
   }   
}