Lazy Resolution with Func<TService>

Feb 12, 2009 at 9:35 PM

In some of my classes I like to delay the loading of dependencies for as long as possible, and I do this by accepting a Func<TService> as a ctor parameter rather than an instance of TService.

I was wondering whether it would be possible to add the ability to resolve a Func<TService> from a container even when I've only registered TService. Since you know how to instantiate TService, if I ask for a Func<TService> then you should be able to hand me a function that wraps up the Func<Container, TService> I've already given you, automatically passing in "this" as the parameter.

Then this sort of thing would be possible:

interface IBar { ... }
class Foo
    public Foo(Func<IBar> barFactory) { ... }

builder.Register<IBar>(c => new Bar());
builder.Register<IFoo>(c => new Foo(c.Resolve<Func<IBar>>()));

The container would resolve Func<IBar> by returning a function that resolves IBar, passing itself into "c".

Does that make sense? I really think that would be a killer feature. I don't know if other IoC containers do this.

Feb 26, 2009 at 6:55 PM
This discussion has been copied to a work item. Click here to go to the work item and continue the discussion.
Jul 24, 2009 at 4:39 AM
Edited Jul 24, 2009 at 4:40 AM

Ok, so I feel a bit silly posting this after all this time, but I just had a flash of insight.

If I have a method like this:

public void DoStuff(Func<Foo> fooFactory)

... then right now I can call it like this:


However, it has just occurred to me that I can also call it like this:


Container.Resolve<Foo> is just a Func that returns a Foo, so I can pass that directly without having to call LazyResolve<Foo>. It also works if the function requires parameters - you just pass container.Resolve<Foo, Bar, int, string> or whatever.

Do we need LazyResolve? Do you think the former is more readable, or could we ditch LazyResolve and just pass the Resolve method pointer around like that?


Jul 24, 2009 at 1:09 PM

Good point Matt.

I'd still keep LazyResolve as it makes it more explicit. Passing the reference to Resolve is not evident enough I think (I missed that one too :)).

Jul 24, 2009 at 1:21 PM

Yeah I do agree that LazyResolve is more explicit and easier to understand.

I also wonder whether there's a (very small) performance gain by using LazyResolve. If I pass LazyResolve<Foo>() to a method, I'm passing the actual function that I used to register Foo with. If I pass Resolve<Foo> then I'm passing a pointer to a method which can "find" that function. Am I right? It's like LazyResolve is "one level lower" than the alternative.