2015-06-22 2 views
0

A Mef CompositionContainer не может разрешить зависимости Autofac при использовании в соответствии с документацией по адресу http://docs.autofac.org/en/latest/integration/mef.html.Невозможно разрешить зависимости Autofac от Mef CompositionContainer при использовании в соответствии с документацией

У меня есть большая база кода, которая широко использует ServiceLocator и singletons ... Сервисный локатор делает все создание объектов, состав и т. Д. С помощью кешированного System.ComponentModel.Composition.Hosting.CompositionContainer. (Также обратите внимание, что в настоящее время мы используем/нуждаемся в поддержке метаданных) Я пытаюсь перейти от этого к более современной архитектуре. Чтобы это сработало, существующий Mef-based («CompositionContainer» -сервер) должен будет сотрудничать с контейнером Autofac IoC.

Следующая функция

  1. Создает Мэф CompositionContainer
  2. Демонстрирует, что MEF способен решить простой экспорт
  3. конфигурирует Autofac регистрироваться MEF и экспортировать AutofacExport в MEF, используя расширение .Exported метод.
  4. Демонстрирует, что Autofac может разрешить создание mef-компонента с зависимостями, определенными в Autofac
  5. Демонстрирует, что Mef не может разрешить экспортированный компонент компонента с зависимостями Autofac.

Исключение составляет: ImportCardinalityMismatchException("No exports were found that match the constraint: ContractName MefExportWithDependency RequiredTypeIdentity MefExportWithDependency".

public void MefResolve_ObjectWithDependency_CanResolveWhenAutofacRegistersDependeyncy2() 
{ 
    //1. Initialize Mef 
    var composablePartCatalogs = new List<ComposablePartCatalog> 
    { 
     new AssemblyCatalog(Assembly.GetExecutingAssembly()) 
     //A lot more here.. 
    }; 

    var aggregateCatalog = new AggregateCatalog(composablePartCatalogs); 
    var container = new CompositionContainer(aggregateCatalog, true); 
    //2. As expected this is resolved 
    container.GetExport<MefExport>().Should().NotBeNull(); 

    //3. Initialize Autofac 
    var builder = new ContainerBuilder(); 
    builder.Register(c => new AutofacExport()).Exported(x => x.As<AutofacExport>()); 
    builder.RegisterComposablePartCatalog(aggregateCatalog); 

    var ioc = builder.Build(); 

    //4. Here Autofac is correctly providing the dependency to the mef ImportingConstructor 
    ioc.Resolve<MefExportWithDependency>().AutofacExport.Should().NotBeNull(); 

    //5. The next line will throw ImportCardinalityMismatchException 
    container.GetExport<MefExportWithDependency>(); 
} 

Там выше код ожидает, что следующие классы должны быть определены:

public class AutofacExport { } 

[Export] 
public class MefExport { } 

[Export] 
public class MefExportWithDependency 
{ 
    public AutofacExport AutofacExport { get; set; } 

    [ImportingConstructor] 
    public MefExportWithDependency(AutofacExport autofacExport) 
    { 
     AutofacExport = autofacExport; 
    } 
} 

Примечание: Я также имел взглянуть на https://www.nuget.org/packages/MefContrib.Integration.Autofac/ - который обещает интегрировать MEF с Autofac. Однако я не могу найти соответствующую документацию о том, как ее настроить, и пакет не имеет большого количества использования.

ответ

0

Возможно, вы неправильно поняли, как должен работать пакет Autofac.Mef. Несмотря на то, что Autofac приносит элементы MEF, позволяя Autofac понять атрибуты экспорта и импорта и элементы, зарегистрированные в каталогах MEF, , это односторонняя операция - это не приводит к регистрации Autofac в MEF или позволяет MEF CompositionContainer использовать Autofac ,

Я считаю, что вы хотите, чтобы пакет MefContrib.Integration.Autofac вы упомянули, что, по-видимому, позволяет вещам двигаться в другом направлении - от Autofac до MEF.

Хорошее место, чтобы увидеть, как это работает, находится в их хранилище, где у них есть some unit tests, где показана интеграция, где MEF разрешает объекты Autofac. Вот один из таких тестов:

[Test] 
public void ExportProviderResolvesServiceRegisteredByTypeTest() 
{ 
    // Setup 
    var builder = new ContainerBuilder(); 
    builder.RegisterType<AutofacOnlyComponent1>().As<IAutofacOnlyComponent>(); 
    var autofacContainer = builder.Build(); 
    var adapter = new AutofacContainerAdapter(autofacContainer); 
    var provider = new ContainerExportProvider(adapter); 

    var component = provider.GetExportedValue<IAutofacOnlyComponent>(); 
    Assert.That(component, Is.Not.Null); 
    Assert.That(component.GetType(), Is.EqualTo(typeof(AutofacOnlyComponent1))); 
} 

Как вы можете видеть, что у них есть адаптер для контейнеров Autofac, что своего рода «новообращенных» их в нечто MEF может понять. У них также есть some unit tests showing bi-directional integration - MEF, разрешающий Autofac, Autofac, разрешающий MEF.

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

+0

Спасибо! - Я боялся, что это односторонняя операция. К сожалению, я не нашел ничего, что указывало бы это в документации Autofac. Мне придется проанализировать немного больше, чтобы проверить, имеет ли смысл добавить (довольно старый) пакет MefContrib. –

+0

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

+0

Спасибо @TravisIllig, если класс имеет атрибут ImportingContructor, делает ли это невозможным запросить другую зависимость, зарегистрированную Autofac? то есть '' 'public myClass (IMefService mefService, IAutofacService afService)' '' – Chazt3n

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