2012-03-08 1 views
0

Я создал каталог сборки:Как управлять обнаружением и составом в качестве двух отдельных проблем?

private CompositionContainer GetContainer() { 
    // initialize directory info 
    ExtensionDirectory = new DirectoryInfo(settings.ExtensionsPath); 
    // directory catalog 
    var dirCatalog = new DirectoryCatalog(ExtensionDirectory.FullName); 

    return new CompositionContainer(dirCatalog); 
    } 

Содержимое контейнера будет загружать все сборки в каталоге, как и ожидались. Я вообще не хочу ничего сочинять, потому что у меня есть конструкторы, которым будут вводиться зависимости.

Что я хочу сделать, это использовать AssemblyCatalog в качестве репозитория; запрос для конкретного экспорта, передать зависимость конструктора, а затем составить только частей, участвующих в этом процессе.

Из того, что я понимаю, если бы я должен был назвать

_container.ComposeParts(this); 

... без предоставления экспорта для [ImportingConstructor] с, то ни одна из частей не будут включены в _container.

Для облегчения запросов к контейнеру, у меня есть метод следующим образом:

public Lazy<IEntity> GetPart(Func<Lazy<IEntity, IEntityMetaData>, bool> selector) { 
    var entity = _container.GetExports<IEntity, IEntityMetaData>() 
          .Where(selector) 
          .Select(e => e as Lazy<IEntity>) 
          .FirstOrDefault(); 

    return entity; // this will be passed up to the composition service 
    } 

Кажется, что GetExports<T, M>() не будет возвращать экспорт, содержащий [ImportingConstructor], если та часть, которая удовлетворяла бы зависимость не входит в контейнере.

Мой подход состоит в том, чтобы иметь контейнер/каталог расширения на низком уровне; служба композиции более высокого уровня получит все части и составит конечный объект. Я решил использовать этот подход, чтобы мы могли добавлять/расширять типы каталогов, доступных в будущем.

ответ

0

Для того, чтобы удовлетворить требования, я создал 3-х классов:

public sealed class CompositionFactory { 
    [Import("Provider")] 
    private IProvider importProvider; 

    /* MEF initialization */ 
} 

[Export("Provider")] 
public sealed class AssemblyProvider : IProvider { 
    private CatalogExportProvider _provider; 
} 

internal sealed class ComposableAggregate { } 

CompositionFactory инициализирует MEF, чтобы открыть AssemblyProvider. Когда поставщик инициализирует:

private CatalogExportProvider InitializeProvider() { 
    // directory catalog 
    var dirCatalog = new DirectoryCatalog(ExtensionDirectory.FullName); 
    return new CatalogExportProvider(dirCatalog); 
} 

... мы возвращаем CatalogExportProvider. Теперь я могу использовать API для CompositionFactory:

public ISomething GetSomething(string ContractName, object ContractParam) { 
    // implementation 
} 

...для запроса правильных наборных частей, используя имя контракта:

public ComposablePartDefinition GetPartDefinition(string ContractName) { 
    return _provider.Catalog.Parts 
        .Where(p => p.ExportDefinitions 
           .Select(e => e.ContractName) 
           .Any(c => c == ContractName)) 
        .FirstOrDefault(); 
} 

Работы затем завершается в вспомогательном классе ComposableAggregate:

internal ISomething Value { 
    get { 
     return _container.GetExport<IEntity>(_contractName).Value; 
    } 
} 

private CompositionBatch CreateBatch() { 
    CompositionBatch batch = new CompositionBatch(); 
    // create composable part from definition 
    ComposablePart importDef = CreatePart(_contractName); 
    batch.AddPart(importDef); 
    return batch; 
} 

private ComposablePart CreatePart(string ContractName) { 
    // get part definition from catalog 
    return _provider.GetPartDefinition(ContractName).CreatePart(); 
} 
1

Я думаю, что эти проблемы уже разделены: обнаружение осуществляется по каталогам, а состав осуществляется поставщиками-экспортерами.

В типичном случае вы просто передаете каталог непосредственно в контейнер, и для удобства он автоматически позаботится о создании для него CatalogExportProvider.

Но вы также можете создать одного или нескольких поставщиков экспорта и передать их в контейнер с помощью this constructor overload. (Вы можете также установить SourceProvider указать обратно в контейнер после этого, так что экспортные провайдеры могут использовать друг друга.)

Вы можете создавать свои собственные ExportProvider реализации, и они даже не должны быть опираясь на каталоги.

+0

Да, они разделены - возможно, лучший термин был бы независимым. У нас есть каталоги, которые будут дополнениями к сервису композиции. Запрос службы для объекта и полностью скомпонованного объекта будет возвращен. – IAbstract

+0

Я думаю, что собираюсь изучить модель конвенции MEF. Я думаю, что он предложит больше гибкости в том, как я хочу, чтобы обнаруженные части были обнаружены. – IAbstract

+0

На самом деле, я только что нашел ваш блог: http://mindinthewater.blogspot.com/2011/03/mef-attribute-less-registration.html – IAbstract

Смежные вопросы