2013-12-14 16 views
20

Ich arbeite an einer Anwendung mit Caliburn.Micro und Autofac.Autofac und Func Fabriken

In meiner Komposition Wurzel Ich bin jetzt vor einem Problem mit Autofac: Ich habe die global verwendet IEventAggregator in meine FirstViewModel zu injizieren, und eine zweite IEventAggregator, die nur von diesem FirstViewModel verwendet werden muss, und es ist Kinder.

Meine Idee war es, die zweite als Owned<IEA> injiziert werden, und es funktioniert, der Container bietet eine andere Instanz von IEA.

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

Das Problem kommt, wenn ich die Ereignis-Aggregatoren zum SecondViewModel zu bieten haben.

Um das SecondViewModel zu erstellen, verwende ich eine Factory-Methode wie Func<IEA, SecondVM>. Die SecondViewModel Konstruktor ist die folgende:

public SecondViewModel(IEventAggregator globalEA, IEventAggregator localEA) {}

I der Behälter wollen, dass die erste als registriert man injizieren, und die zweite wird die IEA-Parameter des Func<IEA, SecVM> sein.

dies ist die Funktion, die ich in den Behälter eingetragen:

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

aber wenn es durch die FirstViewModel ich folgende Fehlermeldung erhalten aufgerufen wird:

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.

ich, wo das Problem kann nicht verstehen, Ist, kannst du mir bitte helfen, was fehlt mir?

Vielen Dank.

Antwort

38

Sie rufen secVMFactory außerhalb Ihres FirstViewModel Konstruktors an, so dass zu diesem Zeitpunkt die ResolveOperation entsorgt wird und die c.Resolve in Ihrer Fabrikmethode die Ausnahme auslöst.

Zum Glück ist die Ausnahmemeldung ist sehr anschaulich und sagen Ihnen, was zu tun ist:

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

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

Statt c.Resolve zu rufen Sie die IComponentContext von c und verwenden, die in Ihrem Werk func lösen müssen

+0

haha ​​Ich habe versucht, das zu tun, aber ich habe es die innere Funktion, so habe ich immer den gleichen Fehler bekommen! +1 noch eine Frage: sollte ich es bei jeder Registrierung tun, um eine Instanziierung von VM-Bestellungen zu verhindern? – Sergio

+0

Es hängt von Ihren Anforderungen ab, Sie können immer 'c.Resolve ();' wenn Sie einen 'Func' in den Container registrieren oder tun Sie es nur in den Fällen, in denen Sie' Resolve' aufrufen müssen deine Fabrik. – nemesv

+0

Sie können mehr über dieses Problem in der Post [Der seltsame Fall eines Deadlock in Autofac] (http://www.continuousimprover.com/2015/01/the-curious-case-of-deadlock-in-autofac) lesen. html) –