Рассмотрим следующий пример кода, который использует MEF для создания объекта типа Importer
, который импортирует объект типа ImporterExporter
, который, в свою очередь, импортирует объект типа Exporter
, то есть Importer -> ImporterExporter -> Exporter
. Каталог управляется CompositionUtility
(очевидно, упрощенный для этого примера).
Я знаю, что MEF будет рекурсивно разрешать импорт импортированных частей. Однако, поскольку я хочу иметь возможность создавать экземпляры каждого из этих классов независимо, каждый класс с импортом также составляет себя в своем конструкторе для разрешения этого импорта.
using System;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.Reflection;
namespace MefRecursionSample
{
class Program
{
static void Main(string[] args)
{
// var importerExporter = new ImporterExporter(); // include this and composition will work
var importer = new Importer();
Console.Write(importer.ImporterExporter.Exporter.Value); // should print 7
Console.ReadKey();
}
}
class CompositionUtility
{
static CompositionUtility()
{
var executingAssembly = Assembly.GetExecutingAssembly();
var assemblyCatalog = new AssemblyCatalog(executingAssembly);
_compositionContainer = new CompositionContainer(assemblyCatalog);
}
private static CompositionContainer _compositionContainer;
private static bool _isComposing;
public static void Compose(object part)
{
_compositionContainer.ComposeParts(part);
}
}
class Importer
{
public Importer()
{
CompositionUtility.Compose(this);
}
[Import]
public ImporterExporter ImporterExporter { get; set; }
}
[Export]
class ImporterExporter
{
public ImporterExporter()
{
CompositionUtility.Compose(this);
}
[Import]
public Exporter Exporter { get; set; }
}
[Export]
class Exporter
{
public int Value { get { return 7; } }
}
}
Выполнение кода как есть приводит к ошибке композиции «ComposablePart типа MefRecursionSample.Importer 'не может быть перекомпонован ....», очевидно потому, что я пытаюсь явно составить что-то, что MEF также хочет составить.
Что меня удивило, так это то, что когда я включил первую строку метода Main
, т.е. создал объект типа ImporterExporter
без MEF, эта «двойная композиция» больше не вызывала исключения. Это почему?
Кроме того, как я могу заставить его работать так, чтобы я мог создать каждый из них независимо, но при этом заставить их составлять себя, когда они связаны, как в образце. Я решил, что введу логический флаг _compositionInProgress
на CompositionUtility
и немедленно вернусь из Compose()
, когда флаг будет установлен, чтобы избежать рекурсивной композиции. Есть ли способ лучше?