I have the following registration
builder.Register<Func<Type, IRequestHandler>>(
c => request => (IRequestHandler)c.Resolve(request));
Basically I am trying to register a factory method that resolves an instance of IRequestHandler from a given type.
This works fine until the version 2.4.3.700. But now I am getting a the following error..
Cannot access a disposed object. Object name: 'This resolve operation has already ended. When registering components using lambdas, the IComponentContext 'c' parameter to the lambda cannot be stored. Instead, either resolve IComponentCo开发者_JAVA技巧ntext again from 'c', or resolve a Func<> based factory to create subsequent components from.'.
UPDATE
I was trying to limit autofac's exposure to the rest of the projects in the solution. Nick, thanks for the hint, now my registration looks like this...
builder.Register<Func<Type,IRequestHandler>>(c =>
{
var handlers = c.Resolve<IIndex<Type,RequestHandler>>();
return request => handlers[request];
});
The c
in this expression is a temporary, so this code while previously functional, is broken. Autofac 2.4.5 detects this problem while earlier versions silently ignored it.
To fix the issue, explicitly resolve IComponentContext
:
builder.Register<Func<Type, IRequestHandler>>(c => {
var ctx = c.Resolve<IComponentContext>();
return request => (IRequestHandler)ctx.Resolve(request));
});
The functionality you're emulating here might be better represented using keys and indexes, e.g. see Interrupted chain of IoC or http://code.google.com/p/autofac/wiki/TypedNamedAndKeyedServices.
I had a similar problem as the user6130. I wanted to avoid using IIndex
in my class implementation and pass in a service resolver into my constructor instead.
So now I have my service implementation with the following constructor:
public MvcMailer(Converter<string, MailerBase> mailerResolver)
{
_resolver = mailerResolver;
}
I wanted to used keyed services without directly relying on the Autofac namespace. I was getting the same error until I restructured the configuration as such.
1) Scan for all my mailer implementations and index via class name (could be improved)
builder.RegisterAssemblyTypes(System.Reflection.Assembly.GetExecutingAssembly())
.Where(t => t.Name.EndsWith("Mailer")).Keyed<Mvc.Mailer.MailerBase>(t => t.Name.Replace("Mailer", "").ToLower());
2) Register the converter in Autofac config
builder.Register<System.Converter<string,Mvc.Mailer.MailerBase>>(c => {
var all = c.Resolve<Autofac.Features.Indexed.IIndex<string,Mvc.Mailer.MailerBase>>();
return delegate(string key)
{
return all[key];
};
});
3) Register like other types of components and let Autofac handle the Converter injection
builder.RegisterType<Mailers.MvcMailer>().As<Mailers.IMailer>();
精彩评论