我需要将泛型类型参数作为接口,但是我想在泛型类(SomeGenericType)中实例化类型,如下所示:
class Program
{
static void Main(string[] args)
{
var val = new SomeGenericType<ISomeInterface>();
Console.ReadKey();
}
}
internal class SomeGenericType<T> where T : new()
{
public SomeGenericType()
{
var test = new T();
}
}
public class SomeClass : ISomeInterface
{
public string TestVal { get; set; }
}
public interface ISomeInterface
{
string TestVal { get; set; }
}
这会抛出以下编译时错误:
“ISomeInterface必须是具有公共无参数构造函数的非抽象类型,以便在泛型类型或方法中将其用作参数'T'SomeGenericType”
我明白为什么会发生这种情况,但是我想知道这个问题是否有任何解决办法?
感谢。
答案 0 :(得分:6)
不,new()
约束要求可以使用语法
new T()
对于抽象类或接口来说,这显然不是真的,只有具有公共无参数构造函数的具体类。
您可以通过删除约束并使用:
将问题推迟到运行时Activator.CreateInstance<T>()
而是创建对象。然后,只要运行时使用的实际类型满足这些约束,您的代码就会按照您的意愿运行。但是,如果您尝试使用接口或抽象类,则会遇到运行时错误。
在您的特定情况下,此行会抛出异常
var val = Activator.CreateInstance<SomeGenericType<ISomeInterface>>();
您已经过了编译时错误,但没有效果。
答案 1 :(得分:2)
另一种想法,可能是无关紧要的,但看起来您正在寻找一种方法来请求ISomeInterface
,并提供了一个“默认”实现SomeClass
的实例。这是控制反转(IOC)容器可以为您处理的事情。如果你想进一步调查,你可以看看Spring.NET,Microsoft Unity,AutoFac,LinFu或许多其他框架之一。
答案 2 :(得分:1)
这里的问题是new
约束与具体类型实现有关。这不能用于简单的接口或抽象类,因为它们不能直接实例化。你必须在这里提供一个具体的课程
var val = new SomeGenericType<SomeClass>()
答案 3 :(得分:1)
问题是,编译器无法知道要为给定接口实例化哪个类。正如大卫M指出的那样:
这是控制反转(IOC)容器可以为您处理的事情
我认为使用框架可能会因为这个简单的要求而过度杀戮。你能做的就是创建一个你自己的Factory
类:
public class Factory
{
Dictionary<Type, Type> typeMapping = new Dictionary<Type, Type>();
public void Register<IType, CType>()
{
typeMapping.Add(typeof(IType),typeof(CType));
}
public IType Create<IType>()
{
Activator.CreateInstance(typeMapping[typeof(IType)]);
}
}
进行一些健全性检查,这个类应该可以使用了。