C#如何将对象转换为运行时类型?

时间:2019-04-26 19:56:19

标签: c# reflection

如何将object转换(或转换,如果不可能或合理转换)为其运行时类型?我可以使用反射来获取runtimeType,但无法弄清楚如何使用List<string>来获取property.GetValue-我知道我可以显式地执行as List<String>,但这是一种-类型的软代码引擎,直到运行时才知道类型。

感谢您的帮助-谢谢! (但是请寻找代码解决方案,而不是“您不应该这样……”答案)

// trimmed-down example class
class Bus { public List<string> Passengers {get;set;} }

// create new instance of class
var obj = new Bus();

// get property value using reflection
var listPropertyName = "Passengers";
var property = GetType(obj).GetProperty($"{listPropertyName}");
var runtimeType = property.PropertyType;

// returns object, but I want List<string> instead 
// (or whatever it is; could be different types like T, List<T>, etc.)
var val = property.GetValue(obj);

// doesn't work (assigns null), expects compile-time type
var val = property.GetValue(obj) as runtimeType; 

1 个答案:

答案 0 :(得分:3)

TL; DR

您不能将某些内容转换为运行时指定的未知类型。这意味着在代码中,除非使用更多的反射,否则您将不知道对象的属性或方法是什么。在那种情况下,铸造它的目的是什么?


有时我们处理直到运行时才知道的类型。但是除非类型真的没有关系,否则对象是无用的,除非我们可以将其强制转换为代码中指定的某个预定类型,而不是在运行时。

在这一行代码中:

var val = property.GetValue(obj); 

val的声明类型由编译器推断。该类型为object,因为这是GetValue返回的类型。对象的实际类型可以是stringintList<Foo>,无论如何。但是您拥有类型val的变量object

如果您可以这样做:

var val = property.GetValue(obj) as runtimeType;    

那么val的编译时类型是什么?由于runTimeType是运行时值,它怎么有呢?该对象是无用的,除非您可以调用方法或检查其属性。但是除非知道更多类型,否则您将无法做到这一点。但是,如果您要这样做,则强制转换是没有意义的。

在您发布的代码的下游,您可能想对包含其方法或属性的对象进行实际操作。这意味着知道您认为是什么类型,并将其强制转换为该类型。那将是您的代码中指定的类型,而不是在运行时确定的类型。

例如:

var val = property.GetValue(obj); // I know this is a string
var myString = (string)val;
var findX = myString.IndexOf("X");

我认为它是string,所以我将其转换为string。 (在那里可能会有其他检查。)现在,我已经对其进行了强制转换,有了一个声明为类型string的变量,并且可以将其用作字符串。 (除非它不是string,否则它将引发运行时异常。)

这是强制转换的好处-它允许我们将某些东西分配给具有我们指定类型的强类型变量,然后相应地使用它。强制转换为未知类型不会使我们受益。


冒着增加混乱的风险:有人可能会说泛型表示运行时未指定的类型,但这并非完全正确。 List<T>并未指定T是什么,但是如果您创建List<T>,则将以某种方式在代码中指定类型。在绝大多数正常情况下,我们必须了解某个对象的类型,否则该对象对我们毫无用处。