CompositionContainer MEF. ComposeParts — загружающийся независимо от того, что может быть разрешено, и ошибки игнорирования

Самая большая проблема, которую я имею до сих пор с MEF, состоит в том что, когда я составляю части в своей сменной обертке загрузчика, загружая полностью залоги, когда это находит проблему разрешения импорта с одним из блоков. Идеально, я хотел бы, чтобы ComposeParts показал своего рода, "игнорируют и продолжают" поведение, потому что идеальный пользовательский опыт повлек бы за собой загрузку как можно больше плагинов и просто входа события, когда определенному плагину не удается загрузиться. Я не смог найти информацию об этом в документации где угодно.

Если у Вас есть какие-либо другие предложения для того, как решить это, я слушаю!

5
задан Dave 4 June 2010 в 13:05
поделиться

2 ответа

В примере Вима есть основные идеи, но вместо того, чтобы тянуть контейнер напрямую, я бы посоветовал вам выполнить 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, если плагин делает что-то не так.

10
ответ дан 13 December 2019 в 05:31
поделиться

Вы можете использовать параметр 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
       }
   }   
}
2
ответ дан 13 December 2019 в 05:31
поделиться
Другие вопросы по тегам:

Похожие вопросы: