I have a problem with casting a generic class to the interface it is implementing.
My code is like this:
interface foo
{
void foobar();
}
class bar: foo
{
public void foobar()
{
throw new NotImplementedException();
}
}
now I have my factory that creates instances of my classes by the interface, mostly a simple microkernel (service locator). I will simplify it here. Normally it will look up the implementing class from the configs and the factory take the type as T but that doesn't matter for the problem I have.
public static class Factory
{
public static Lazy<foo> CreateLazyInstance()
{
Lazy<foo> instance;
Type type = typeof(bar);
Type lazyType = typeof(Lazy<>);
Type toContruct = lazyType.MakeGenericType(type);
instance = (Lazy<foo>)Activator.CreateInstance(toContruct);
return instance;
}
}
If will fail at:
instance = (Lazy<foo>)Activator.CreateInstance(toContruct);
and claim with an InvalidCastException that it is not possible to cast the type Lazy<bar>
to Lazy<foo>
.
Is there any way to tell the CLR that this cast will work or to workaround this problem?
No -
Lazy<T>
is invariant - so aLazy<string>
is not aLazy<object>
for example. (As pointed out in comments, it couldn't be declared as covariant inT
, as it's a class, not an interface or delegate.)However, you can convert one to the other easily enough:
Also,
Func<T>
is covariant, so this will work too:(Not that you particularly need a method for that - if you've got a
Func<TInput>
, just construct aLazy<TOutput>
directly.)You must do you foo generic parameter : new():
And change you code to find a constructor and call it:
An easier way to do this would be to pass in a lambda to the Lazy constructor. So, your code would look like the following: