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

发布于 2024-09-05 00:49:51 字数 212 浏览 6 评论 0原文

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

如果您对如何解决此问题有任何其他建议,我会倾听!

The biggest problem I'm having so far with MEF is that when I compose parts in my plugin loader wrapper, loading completely bails when it finds an import resolution problem with one of the assemblies. Ideally, I'd like ComposeParts to exhibit some sort of "ignore and continue" behavior, because the ideal user experience would entail loading as many plugins as possible, and simply logging an event when a specific plugin fails to load. I haven't been able to find information about this in the documentation anywhere.

If you have any other suggestions for how to solve this, I'm listening!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

陪你搞怪i 2024-09-12 00:49:51

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 调用中会出现的异常。

Wim's example has the basic ideas but instead of pulling on the container directly I would suggest you do a Lazy ImportMany like such:

[Export]
public class MyApplication
{
   [ImportMany(typeof(IPlugin))]
   public IEnumerable<Lazy<IPlugin>> Plugins { get; set; }
}

Then you can initialize the plugins one by one and catch any errors from them like:

void InitializePlugins()
{
   foreach (Lazy<IPlugin> plugin in Plugins)
   {
       try
       {
          plugin.Value.Initialize();
       }
       catch (CompositionException e)
       {
          // Handle the error accordingly
       }
   }   
}

The actual plugin will not be created until you pull on .Value the first time and that is when errors will occur if the plugin has bugs in the constructor or property setters of the imports. Also note that I'm catch CompositionException which is what will come out of the .Value call if the plugin does something wrong.

压抑⊿情绪 2024-09-12 00:49:51

您可以使用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
       }
   }   
}

You can use the AllowDefault parameter. Setting it to true on an import will cause the dependency to be null if no available part can satisfy the import.

public class MyComponent
{
    [Import(AllowDefault=true)]
    public IMyDependency MyDependency { get; set; }
}

To load all available plugins but ignore those which cannot be loaded because of missing parts, [ImportMany] will already do what you want by default:

[Export]
public class MyApplication
{
   [ImportMany(typeof(IPlugin))]
   public IEnumerable<IPlugin> Plugins { get; set; }
}

Note that the above techniques only eliminate composition errors that are caused by missing parts. If a part and its imports are actually available, but it then throws an unexpected exceptions when the constructor is called, then you will still get an exception. To ignore such problems which are not composition-related, you can invoke the container directly like this:

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
       }
   }   
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文