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

C# 泛型类,如何在运行时设置类型?,c#,generics,runtime,generic-programming,C#,Generics,Runtime,Generic Programming,我已经创建了一个泛型类,但是我知道运行时中的类型,而不是设计中的类型,所以我想知道如何在运行时设置类型 例如,我有: public class MyGenericClass<T> { .... } 公共类MyGenericClass { .... } 然后我试着使用它。我在另一个类中有一个方法,它使用这个泛型类。在这个类的构造函数中,我作为参数接收我想要的类型,因此我有一个type属性,在其中保存我需要的类型。所以我试着这样做: MyGenericClass<_typeNe

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

例如,我有:

public class MyGenericClass<T>
{
....
}
公共类MyGenericClass
{
....
}
然后我试着使用它。我在另一个类中有一个方法,它使用这个泛型类。在这个类的构造函数中,我作为参数接收我想要的类型,因此我有一个type属性,在其中保存我需要的类型。所以我试着这样做:

MyGenericClass<_typeNeeded> myClass = new MyGenericClass<typeNeeded>();
MyGenericClass myClass=新的MyGenericClass();
但这是行不通的

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

我正在使用C#4.0

谢谢。 戴姆洛克

编辑:我想做的是以下几点。我有一个类需要对数据库进行一些查询。这个查询总是返回相同的信息,一个类,但是包含这个类的信息来自不同的表。这是因为我需要确定使用什么查询。要决定使用什么查询,我使用接收的类型

因为这个原因,我不知道设计中的类型,但是在运行时


我可以使用一个接口,它将由to类实现,并使用用正确的类实例化的接口,但这使我在实例化时有了一个开关或if,这就是我试图避免的,我想要更通用的东西。另外,如果我使用这个解决方案,在实例化时有一个If,我可以创建泛型类,这样我就只有一个类,而且它更易于维护。

看看这个方法。您可以使用它创建一个
Type
实例(然后可以使用该实例创建该类型的实例),并在运行时确定泛型参数值。但是要注意,无论何时处理对象的一般特征,都需要更多的反射;您不能在类型为带有变量类型参数的泛型类型的代码中创建变量。

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

public interface IMyInterface
{
...
}

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

IMyInterface myClass = new MyGenericClass<typeNeeded>();
或者,如果是这样的话,那么所有的T’类型之间都有一个额外的关系,这样所有的T’类型都有一个共同的超类,比如BaseT,您可以进行更改

public T GetT(){...}
致:


您可以用另一种方式创建类,将要使用的类型传递给构造函数并利用关键字

例如:

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

如果要处理对象,则在编译时知道方法名称,这意味着您可以使用接口

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);

如果没有广泛的思考,这是不可能的。你看到了吗?为什么不使用dynamic关键字?你能更具体一点吗?你想得到什么样的结果?@Mark M:在这个例子中,我是如何使用这个方法的?因为该方法返回一个对象,但我必须首先声明变量MyGenericClass miVariable=CreateGeneric…),但问题是我不知道t的类型。但该示例喜欢我正在寻找的内容。
TypeRequired
是OP问题中的一个变量,因此
new MyGenericClassy()
不会编译。好的,说得好。无论如何,如果我们知道T不是任何类型,而是我们知道的少数类型之一,并且我们需要简单而快速的解决方案(没有反射),那么我们可以使用带有switch语句的工厂进行类型实例化,并坚持使用此解决方案。让我们看看OP是否想走这条路,是否需要更多信息。
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);