泛型类,如何在运行时设置类型

本文关键字:运行时 置类型 泛型类 | 更新日期: 2023-09-27 18:36:47

我创建了一个泛型类,但我知道运行时中的类型,而不是设计中的类型,所以我想知道如何在运行时中设置类型。

例如,我有:

public class MyGenericClass<T>
{
....
}

然后我尝试使用它。我在其他类中有一个方法,它使用这个泛型类。在此类的构造函数中,我接收所需的类型作为参数,因此我有一个 type 属性,在其中保存所需的类型。所以我正在尝试这个:

MyGenericClass<_typeNeeded> myClass = new MyGenericClass<typeNeeded>();

但这行不通。

如何在我创建的类中设置运行时的类型?

我正在使用 C# 4.0。

谢谢。戴姆罗克。

编辑:我想做的是以下内容。我有一个类需要对数据库进行一些查询。此查询始终返回相同的信息,即类,但包含此类的信息来自不同的表。这是因为我需要确定要使用的查询。为了决定使用哪个查询,我使用我收到的类型。

正是由于这个原因,我不知道在设计类型,但在运行时。

我可以使用一个接口来实现它到类,

并使用使用正确的类实例化的接口,但这让我在实例化的那一刻有一个开关或一个 if,这就是我试图避免的,我想要更通用的东西。此外,如果我使用此解决方案,要在实例化的那一刻拥有一个 if,我可以创建泛型类,所以我只有一个类,它会更易于维护。

泛型类,如何在运行时设置类型

看看MakeGenericType方法。您可以使用它来创建Type实例(然后可用于创建该类型的实例),并在运行时确定泛型参数值。但是,请注意,在处理该对象的通用功能时,您将需要更多的反思;不能在类型为具有变量类型参数的泛型类型的代码中创建变量。

您可以通过另一种方式创建类,将要使用的类型传递给构造函数并利用 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);
    }
}

如果您考虑一下,就没有理由拥有一个类型在运行时确定的泛型。泛型提供强类型,但这只有在编译时知道类型时才有可能。这是泛型的最大好处之一,它提供了安全性,因为您知道对象可以执行哪些操作。在运行时,如果您不知道自己得到的是哪种类型,那将违背这一目的,您将不得不深入研究强大(但有时是危险的)反思世界。例如

List<DateTime> list = new List<DateTime>();
foreach (DateTime item in list)
   item.Minute + ": " + item.Hour

因为我在 COMPILE 时知道类型,所以我可以将其存储在泛型容器中,并且在使用它时具有类型安全性。我知道该项目具有分钟和小时属性。


如果要根据对象的类型执行操作,请使用 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);

我没有足够的关于你的代码的信息,但也许你可以使用简单的多态性:

public interface IMyInterface
{
...
}
public class MyGenericClass<T> : IMyInterface
{
....
}
IMyInterface myClass = new MyGenericClass<typeNeeded>();

您还可以将其与工厂设计模式混合使用,以便其他一些类将负责根据一些运行时知识实例化您的类型。

当然,这假设你的MyGenericClass没有这样的方法:

public T GetT(){...}

或者,如果确实如此,则所有 T 类型之间都有一个额外的关系,以便它们都具有共同的超类,比如 BaseT,您可以更改

public T GetT(){...}

自:

public BaseT GetT(){...}