2013-12-14 3 views
20

Я работаю над приложением с использованием Caliburn.Micro и Autofac.Заводы Autofac и Func

В моей композиции корня я теперь столкнулся с проблемой с Autofac: я должен вводить использованную глобально IEventAggregator в мой FirstViewModel, и второй IEventAggregator, который должен быть использован только этим FirstViewModel и это дети.

Моя идея состояла в том, чтобы сделать вторую инъекцию как Owned<IEA>, и она работает, контейнер предоставляет другой экземпляр МЭА.

public FirstViewModel(
    IEventAggregator globalEA, 
    IEventAggregator localEA, 
    Func<IEventAggregator, SecondViewModel> secVMFactory) {} 

Проблема возникает, когда я должен предоставить агрегаторы событий для SecondViewModel.

Чтобы создать SecondViewModel, я использую заводский метод как Func<IEA, SecondVM>. Конструктор SecondViewModel заключается в следующем:

public SecondViewModel(IEventAggregator globalEA, IEventAggregator localEA) {}

Я хочу, чтобы контейнер, чтобы ввести первый как зарегистрированный один, а второй будет параметр МЭА в Func<IEA, SecVM>.

это функция, которую я зарегистрирован в контейнере:

builder.Register<Func<IEventAggregator, SecondViewModel>>(
    c => 
     (ea) => 
     { 
      return new SecondViewModel(
       c.Resolve<IEventAggregator>(), 
       ea); 
     } 
); 

но когда он вызывается с помощью FirstViewModel я получаю следующее сообщение об ошибке:

An exception of type 'System.ObjectDisposedException' occurred in Autofac.dll but was not handled in user code

Additional information: This resolve operation has already ended. When registering components using lambdas, the IComponentContext 'c' parameter to the lambda cannot be stored. Instead, either resolve IComponentContext again from 'c', or resolve a Func<> based factory to create subsequent components from.

Я не могу понять, где проблема Ты можешь помочь мне, что мне не хватает?

спасибо.

ответ

38

Вы звоните secVMFactory вне вашего FirstViewModel конструктора, так к тому времени ResolveOperation расположено и в методе ФАБРИКИ c.Resolve выбросит исключение.

К счастью, сообщение исключением очень содержательный и говорит вам, что делать:

When registering components using lambdas, the IComponentContext 'c' parameter to the lambda cannot be stored. Instead, either resolve IComponentContext again from 'c'

Таким образом, вместо вызова c.Resolve вам нужно разрешить IComponentContext от c и использовать это в вашем заводе FUNC:

builder.Register<Func<IEventAggregator, SecondViewModel>>(c => { 
    var context = c.Resolve<IComponentContext>(); 
    return ea => { 
      return new SecondViewModel(context.Resolve<IEventAggregator>(), ea); 
    }; 
}); 
+0

haha ​​Я попытался это сделать, но я ставлю его внутренней функцией, поэтому я продолжал получать ту же ошибку! +1 еще один вопрос: должен ли я делать это в каждой регистрации, чтобы предотвратить рефакторинг экземпляров виртуального заказа vm? – Sergio

+0

Это зависит от ваших требований, вы всегда можете 'c.Resolve ();' когда вы регистрируете 'Func' в контейнере или просто делаете это только в тех случаях, когда вам действительно нужно вызвать' Resolve' в ваш завод. – nemesv

+0

Подробнее об этой проблеме вы можете прочитать в разделе [Загадочный случай тупика в Autofac] (http://www.continuousimprover.com/2015/01/the-cory-case-of-deadlock-in-autofac. html) –

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