将泛型类强制转换为接口
本文关键字:接口 转换 泛型类 | 更新日期: 2023-09-27 18:07:44
我有一个问题,将泛型类强制转换为它正在实现的接口。
我的代码是这样的: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;
}
}
If将在:
instance = (Lazy<foo>)Activator.CreateInstance(toContruct);
并使用InvalidCastException声明不可能将类型Lazy<bar>
转换为Lazy<foo>
。
是否有办法告诉CLR这个强制转换将工作或解决这个问题?
No - Lazy<T>
是不变的 -所以Lazy<string>
不是Lazy<object>
。(正如在评论中指出的,它不能在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>
就可以了)
更简单的方法是将lambda传递给Lazy构造函数。因此,您的代码看起来像下面这样:
public static Lazy<foo> CreateLazyInstance()
{
Type type = typeof(bar);
return new Lazy<foo>(() => (foo)Activator.CreateInstance(type));
}
您必须执行您的foo泛型参数:new():
public static Lazy<foo> CreateLazyInstance() where foo : new()
并更改代码以找到一个构造函数并调用它:
Type t = typeof(foo);
t.GetConstructor(new type[]{});
return (foo)t.Invoke(new object[]{});