В качестве альтернативы двойному решению CompositionContainer
вы можете подключить его к одному поставщику экспорта и создать его с использованием одного и того же контейнера. В качестве примера я определил следующий контракт и его экспорт:
public interface ILogger
{
void Log(string message);
}
[Export(typeof(ILogger))]
public class ConsoleLogger : ILogger
{
public void Log(string message)
{
Console.WriteLine(message);
}
}
И с моим примером ExportProvider
я ожидаю, что смогу импортировать его экземпляр:
public class TestExportProvider : ExportProvider
{
private readonly object _lock = new object();
private bool _initialised;
[Import]
public ILogger Logger { get; set; }
public void SetCompositionService(ICompositionService service)
{
if (service == null) throw new ArgumentNullException("service");
lock (_lock)
{
if (!_initialised)
{
InitialiseProvider(service);
}
}
}
private void InitialiseProvider(ICompositionService service)
{
service.SatisfyImportsOnce(this);
_initialised = true;
}
protected override IEnumerable<Export> GetExportsCore(ImportDefinition definition, AtomicComposition atomicComposition)
{
if (_initialised)
{
Logger.Log("Getting available exports for '" + definition.ContractName + "'");
// Do work here.);
return Enumerable.Empty<Export>();
}
return Enumerable.Empty<Export>();
}
}
Я предоставляю экземпляр ICompositionService
, который реализует CompositionContainer
, и я выполняю инициализацию впервые, когда я вызываю SetCompositionService
. Он проверяет, была ли она уже инициализирована, и если нет, то запускает и вызывает метод SatisfyImportsOnce
для себя.
Мы бы связали это, что-то вроде этого:
// Build our catalog.
var catalog = new AssemblyCatalog(typeof(Program).Assembly);
// Create our provider.
var provider = new TestExportProvider();
// Create our container.
var container = new CompositionContainer(catalog, provider);
// Register the composition service to satisfy it's own imports.
provider.SetCompositionService(container);
Очевидно, что вы не сможете использовать какой-либо импорт, и ваш ExportProvider
явно создаст для вас, но для всего остального он должен работать.