【问题标题】:C# Getting Type out of a string variable and using it in generic methodC# 从字符串变量中获取类型并在泛型方法中使用它
【发布时间】:2019-02-14 23:38:53
【问题描述】:

我希望能够通过某种方式(即从数据库)获得我收到的字符串值的实际类型,以便我可以在像DoSomething<Type>() 这样的通用方法中使用该类型。

在我的项目中,我的类 PlaneCar 位于 MyCompany.MySolution.Vehicle 命名空间中,就像这样

- MyCompany.MySolution.Vehicle
  |+Interfaces
  |-Implementations
    |-Car
    |-Plane

我收到车辆类型作为字符串。所以,我得到字符串“Car”,这意味着,我需要得到类型Car,这样我就可以在通用方法中使用该类型来注册它,如下所示:

MyFactory.Register<Car>(carId)

所以,MyFactory 是调用 Register() 方法的静态类。

同样,我收到字符串“Plane”,这意味着,我需要获取类型Plane,这样我就可以在上面的通用方法中使用该类型来注册一个平面。

我尝试使用类似的东西

MyFactory.Register<Type.GetType("MyCompany.MySolution.Vehicle.Implementations.Car")>(carId)

,但这不起作用。

【问题讨论】:

  • 您是否尝试过使用Car 的完全限定名称(包括命名空间)?即Type.GetType("MyCompany.MySolution.Vehicle.Implementations.Car")
  • @matt-dot-net 不,它不是重复的。 Rufus,是的,我试过了,不会返回任何东西

标签: c# generics gettype


【解决方案1】:

如果你想调用一个在运行时生成的带有类型参数的通用方法,你可以做这样的事情:

var vehicleString = "Car";

// use the fully-qualified name of the type here
// (assuming Car is in the same assembly as this code, 
//  if not add a ", TargetAssemblyName" to the end of the string)
var vehicleType = 
    Type.GetType($"MyCompany.MySolution.Vehicle.Implementations.{vehicleString}");

// assuming MyFactory is the name of the class 
// containing the Register<T>-Method
typeof(MyFactory).GetMethod("Register")
    .MakeGenericMethod(vehicleType)
    .Invoke(this);

Working Example

就像一个注释:

不是应该如何使用泛型。我只是指出了这种可能性,并没有为您提出的问题提供理想的答案。也许您应该重新考虑您的一些建筑设计选择!

【讨论】:

  • 我不需要从 MyFactory 获取方法。它是一个静态类,所以我可以像解释 MyFactory.Register(carId) 一样使用它。问题在于我解释了如何从字符串“Car”中获取类型 Car,这样我就可以将该类型放入 Register 中。将您的 Register 错误与“vehicleType 是一个变量,但它被用作一种类型”错误。这正是我解释的我试图做的减去你使用 GetMethod 的尝试。
  • 是的。如果不使用反射,就不能将类型变量作为泛型参数传递。我刚刚在我的答案中添加了一个工作示例。
【解决方案2】:

如果Register&lt;T&gt; 做了这样的事情

void Register<T>(int id)
{
    _dictionary.Add(typeof(T), ...);
}

创建一个非泛型重载

void Register(Type t, int id)
{
    _dictionary.Add(t, ...);
}

这个新的重载不是类型安全的,但无论如何都不是从字符串创建类型。

泛型的目的是在保持类型安全的同时获得可变性(不要与动态行为混淆!)。但是,当类型在运行时确定时,类型安全并没有给出,泛型更多的是障碍而不是有用。

请注意,类型安全是由编译器确保的,这在运行时当然不起作用。

【讨论】:

  • 那么,如何从字符串“Car”中获取 Type t,以便将其传递给 Register(Type t, int id)?如前所述,我不知道类型,我有字符串值“Car”,我必须从中获取类型 Car :)
  • 使用Type.GetType。首先查看 typeof(Car).FullName 以查看您必须提供的确切名称。
  • 不,您不能在泛型方法中使用 Type.GetType("")。你不能做 DoSomething(Id),那是行不通的
  • 当然不是作为泛型类型参数,但你可以为我的第二种方法获取Type 对象。 (这就是我建议它的原因)。
  • 谢谢,但我需要将其用作通用参数,想弄清楚,但您的建议肯定有帮助,谢谢
【解决方案3】:

您可以使用包含所有类型的字典,其中包含字符串键:

var d = new Dictionary<String,Type>(); 
d.Add("Car",typeof(Car)); 
d.Add("Plane",typeof(Plane)); 

那么如果你从数据库中获取字符串“Car”,你可以得到这样的类型:

var myType = d["Car"]; 

然后使用myType 作为真正的Type。

【讨论】:

  • 好吧,我的注册方法正试图将它添加到字典中,就像你解释的那样。但正如解释的那样,我的 Register 方法是通用的,所以需要知道能够像 Register(carId) 一样调用它的类型
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多