Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
654 views
in Technique[技术] by (71.8m points)

.net - Autofac and Func factories

I'm working on an application using Caliburn.Micro and Autofac.

In my composition root I'm now facing a problem with Autofac: I have to inject the globally used IEventAggregator into my FirstViewModel, and a second IEventAggregator that has to be used only by this FirstViewModel and it's children.

My idea was to make the second one be injected as Owned<IEA>, and it works, the container provides a different instance of IEA.

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

The problem comes when I have to provide the event aggregators to the SecondViewModel.

To create the SecondViewModel I use a factory method as Func<IEA, SecondVM>. The SecondViewModel's constructor is the following:

public SecondViewModel(IEventAggregator globalEA, IEventAggregator localEA) {}

I want the container to inject the first as the registered one, and the second will be the IEA parameter of the Func<IEA, SecVM>.

this is the function I registered in the container:

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

but when it gets called by the FirstViewModel I get the following error:

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.

I can't understand where the problem is, can you help me please, what am I missing?

Thank you.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You are calling secVMFactory outside of your FirstViewModel constructor so by that time the ResolveOperation is disposed and in your factory method the c.Resolve will throw the exception.

Luckily the exception message is very descriptive and telling you what to do:

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

So instead of calling c.Resolve you need to resolve the IComponentContext from c and use that in your factory func:

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...