将通用类转换为它正在实现的接口时遇到问题.
我的代码是这样的:
interface foo
{
void foobar();
}
class bar: foo
{
public void foobar()
{
throw new NotImplementedException();
}
}
现在我的工厂通过界面创建我的类的实例,主要是一个简单的微内核(服务定位器).我会在这里简化它.通常它会从配置中查找实现类,而工厂将类型视为T,但这与我遇到的问题无关.
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;
}
}
如果失败的话:
instance = (Lazy<foo>)Activator.CreateInstance(toContruct);
并使用InvalidCastException声明无法转换类型Lazy< bar>到Lazy< foo>.
有没有办法告诉CLR这个演员会工作还是解决这个问题?
解决方法:
No – Lazy<T>
是不变的 – 所以Lazy< string>不是懒惰<对象>例如. (正如评论中指出的那样,它不能在T中声明为协变,因为它是一个类,而不是接口或委托.)
但是,您可以轻松地将一个转换为另一个:
static Lazy<TOutput> CreateLazyProxy<TInput, TOutput>
(Lazy<TInput> input) where TInput : TOutput
{
return new Lazy<TOutput>(() => input.Value);
}
而且,Func< T>是协变的,所以这也会有效:
static Lazy<TOutput> CreateLazy<TInput, TOutput>(Func<TInput> func)
where TInput : TOutput
{
return new Lazy<TOutput>(func);
}
(并不是说你特别需要一个方法 – 如果你有一个Func< TInput> ;,只需要直接构造一个Lazy< TOutput> ;.)