我创建了一个泛型类,但我知道运行时的类型,而不是设计中的类型,所以我想知道如何在运行时设置类型。
例如,我有:
public class MyGenericClass<T>
{
....
}
然后我尝试使用它。我在其他类中有一个方法,它使用这个泛型类。在这个类的构造函数中,我接收了我想要的类型作为参数,所以我有一个type属性,我在其中保存了我需要的类型。我正在尝试这个:
MyGenericClass<_typeNeeded> myClass = new MyGenericClass<typeNeeded>();
但这不起作用。
如何在我创建的类中设置运行时类型?
我正在使用C#4.0。
感谢。 Daimroc。
编辑:我想做的是以下内容。我有一个类需要对数据库进行一些查询。此查询始终返回相同的信息,即类,但包含此类的信息来自不同的表。这是因为我需要确定要使用的查询。要决定使用哪种查询,请使用我收到的类型。由于这个原因,我不知道设计中的类型,但是在运行时。
我可以使用它将由类实现的接口,并使用用正确的类实例化的接口,但是这使我在实例化时有一个开关或if,这就是我尽量避免,我想要更通用的东西。另外,如果我使用这个解决方案,在instantion的时刻有一个if,我可以创建泛型类,所以我只有一个类,它会更易于维护。
答案 0 :(得分:4)
查看MakeGenericType
方法。您可以使用它来创建Type
实例(可以用于创建该类型的实例),并在运行时确定通用参数值。但请注意,在处理该对象的通用功能时,您将需要更多的反射;您无法在类型为具有变量类型参数的泛型类型的代码中创建变量。
答案 1 :(得分:3)
您可以用其他方式创建您的类,将构建函数传递给您要使用的类型并利用dynamic
关键字。
例如:
class MyGeneralClass
{
dynamic myVariable;
Type type;
public MyGeneralClass(Type type)
{
this.type = type;
myVariable = Activator.CreateInstance(type);
//And then if your type is of a class you can use its methods
//e.g. myVariable.MyMethod();
}
//If your function return something of type you can also use dynamic
public dynamic Function()
{
return Activator.CreateInstance(type);
}
}
答案 2 :(得分:2)
我没有足够的有关您的代码的信息,但也许您可以使用简单的多态:
public interface IMyInterface
{
...
}
public class MyGenericClass<T> : IMyInterface
{
....
}
IMyInterface myClass = new MyGenericClass<typeNeeded>();
您还可以将其与工厂设计模式混合使用,以便其他一些类将负责基于某些运行时知识实例化您的类型。
这当然假设你的MyGenericClass没有类似的方法:
public T GetT(){...}
或者如果它确实存在所有T'types之间的额外关系,所以它们都有共同的超类让我们说BaseT你可以改变
public T GetT(){...}
为:
public BaseT GetT(){...}
答案 3 :(得分:2)
如果你考虑一下,没有理由拥有一个在运行时确定其类型的泛型。泛型提供强类型,但只有在编译时知道类型才能实现。这是泛型的最大好处之一,它提供了安全性,因为您知道对象可以执行的操作。在运行时如果你不知道你得到了什么类型,那就会失败这个目的,你将不得不深入研究反射的强大(但有时是危险的)世界。例如,
List<DateTime> list = new List<DateTime>();
foreach (DateTime item in list)
item.Minute + ": " + item.Hour
因为我知道COMPILE时的类型,所以我可以将它存储在通用容器中,并且在使用时我有类型安全性。我知道这个项目有一个Minute and Hour属性。
如果要根据对象的类型执行操作,则使用GetType()方法。这是进入运行时类型识别和处理的窗口。
Result PerformQuery(object unknownObject)
{
switch (object.GetType())
{
case typeof(ThisType): Do This; break;
case typeof(ThatType): Do That; break;
}
}
如果要对对象执行某些操作,那么您可以在编译时知道方法名称,这意味着您可以使用接口,
IFood hamburger = new Hamburger();
hamburger.BeEaten();
如果您没有或想要使用界面,您可以使用反射或动态,在这种情况下,如果我知道我想要调用哪种方法,我会使用动态。
Result PerformQuery(object unknownObject)
{
if (object.GetType() == typeof(Pizza))
{
dynamic pizza = unknownObject;
pizza.BakeInOven() // since I checked and know it is type Pizza it is 'somewhat' safe to do this, unless Pizza class changes the name of BakeInOven method.
}
}
最后,如果你不知道你想在编译时调用的方法,你可以使用反射。
string methodName = CalculateWhatMethodShouldBe();
MethodInfo myMethod = unknownObject.GetType().GetMethods().First(m => m.Name == methodName);
MethodInfo.Invoke(unknownObject);