views:

119

answers:

3

I am wondering whether I can upgrade a basic IoC container I am using to support lazy load. So if I have registered IFoo, I would like the IoC container to know how to fulfil both of the following dependencies (the first being the standard way IoC containers work, while the second returns a simple delegate that calls into the container for an IFoo when it is invoked).

public Bar(IFoo x)

public Bar2(Func<IFoo> lazyFoo)

The problem comes when I try to write the code that will actually do this. Is there a syntax that will make the following pseudo-code compile?

public T Resolve<T>()
{
    if (T is Func<X>)
        return (T) () => Resolve(typeof(X));
    return (T)Resolve(typeof(T));
}

Or to put my question another way, if I have a type T, how can I detect if it is an instance of Func<X>, and if so, what is the type of X?

+3  A: 

take a look at this question from this morning - might give you a good start - http://stackoverflow.com/questions/1043755/c-generic-list-t-how-to-get-the-type-of-t

Scott Ivey
Indeed, replace `List` with `Func` and you're done...
Marc Gravell
yes, looks like this will do it for me. thanksNow I have a problem that the compiler won't let me cast from() => Resolve(theArgumentType) back to the original T (even if I try to cast to object first). "Cannot convert lambda expression to type 'T' because it is not a delegate type"
Mark Heath
A: 

In answer to the question in the comment, you need to invoke the lambda expression, not cast it.

SLaks
I don't want to invoke it yet, I want to pass the Func itself back so that the caller can invoke it when they are ready to
Mark Heath
Then you need to cast it to Func<T>.
SLaks
I misunderstood; see second answer.
SLaks
+1  A: 

I misunderstood your question.

It is impossible to do it in one function the way you're trying to because the compiler must have a delegate type to create the lambda as at compile time.

However, this should work.

public T Resolve<T>()
{
    return (T)Resolve(typeof(T));
}

public Func<T> LazyResolve<T>()
{
    return () => Resolve<T>();
}
SLaks
ok I think I understand why its not possible. Shame, because it would be a nice feature for an IoC container.
Mark Heath