我有两个实现一个接口的泛型类。
public interface Interface1
{
//implementation
}
public interface Interface2<T>
{
//implementation
}
class Class1<T>: Interface2<T> where T : Interface1
{
//implementation
}
class Class2<T>: Interface2<T>
{
//implementation
}
我想编写一个返回其中一个类的对象的方法,具体取决于类型T.
Interface2<T> GetObject<T>()
{
if (typeof(Interface1).IsAssignableFrom(typeof(T)))
{
//error
return new Class1<T>();
}
return new Class2<T>();
}
Class1的实现必须限于实现接口的类型。有没有办法将类型T转换为Interface1?现在我收到了错误:类型&#39; T&#39;不能用作类型参数&#39; T&#39;通用类型或方法&#39; Class1&#39;。没有拳击转换或类型参数转换来自&#39; T&#39;到&#39; Test.Interface1&#39;。
答案 0 :(得分:1)
完全反思是:
return (Interface2<T>)Activator.CreateInstance(typeof(Class1<>).MakeGenericType(typeof(T)));
但它很慢(与执行new Foo()
相比较慢)...我找不到任何其他方式。请注意,您已经部分处于反射方向(IsAssignableFrom
)
嗯使用静态类的“缓存”,我们可以作弊......我们可以在运行时生成创建new Class1<T>
并缓存它所需的确切代码。
第一版
static class Maker<T>
{
public static Func<Interface2<T>> Func { get; private set; }
public static Interface2<T> New()
{
if (Func == null)
{
Func = Expression.Lambda<Func<Interface2<T>>>(Expression.New(typeof(Class1<>).MakeGenericType(typeof(T)))).Compile();
}
return Func();
}
}
我使用表达式new Class1<T>
的表达式树。然后:
static Interface2<T> GetObject<T>()
{
if (typeof(Interface1).IsAssignableFrom(typeof(T)))
{
return Maker<T>.New();
}
return new Class2<T>();
}
但我们仍然可以做更多事情。给定T
类型,可以预先计算和缓存if
中GetObject()
的结果。我们在表达式树中移动整个GetObject()
。
static class Maker2<T>
{
public static Func<Interface2<T>> Func { get; private set; }
public static Interface2<T> New()
{
if (Func == null)
{
if (typeof(Interface1).IsAssignableFrom(typeof(T)))
{
Func = Expression.Lambda<Func<Interface2<T>>>(Expression.New(typeof(Class1<>).MakeGenericType(typeof(T)))).Compile();
}
else
{
Func = Expression.Lambda<Func<Interface2<T>>>(Expression.New(typeof(Class2<>).MakeGenericType(typeof(T)))).Compile();
}
}
return Func();
}
}
然后
static Interface2<T> GetObject2<T>()
{
return Maker2<T>.New();
}
使用表达式树的解决方案在第一次用于每个类型T
时非常慢,因为它必须生成表达式树并对其进行编译,但随后它变得非常快。这与使用每次缓慢的Activator.CreateInstance
的版本相比: - )