我有一个简单的程序,它使用反射打印出提供的类的属性和值。
class BaseClass
{
public string A
{
get { return "BaseClass"; }
}
}
class Child1 : BaseClass
{
public string Child1Name {
get { return "Child1"; }
}
}
class Child2 : BaseClass
{
public string Child2Name
{
get { return "Child2"; }
}
}
class Program
{
static void Main(string[] args)
{
var child1 = new Child1();
var child2 = new Child2();
SomeMethod(child1);
SomeMethod(child2);
Console.ReadKey();
}
static void SomeMethod(BaseClass baseClass)
{
PrintProperties(baseClass);
}
static void PrintProperties<T>(T entity)
{
var type = typeof(T);
foreach (var targetPropInfo in type.GetProperties())
{
var value = type.GetProperty(targetPropInfo.Name).GetValue(entity);
Console.WriteLine("{0}: {1}", targetPropInfo.Name, value);
}
Console.WriteLine("");
}
}
问题是它只打印出BaseClass
属性,因为我使用的是泛型并将BaseClass
传入PrintProperties
方法。
输出:
A:BaseClass
A:BaseClass
如何访问Child类的属性?我想输出如下:
A:BaseClass
Child1Name:Child1A:BaseClass
Child2Name:Child2
答案 0 :(得分:6)
此处的问题是您在typeof(T)
中使用PrintProperties
,但示例中的T
为BaseClass
,因为这是您提供的参数类型来自SomeMethod
。
在您的示例中,移除SomeMethod
,直接调用PrintProperties
方法即可。
更简单的方法是使用entity.GetType()
代替typeof(T)
。这样,无论泛型类型是什么,您都将获得对象的真实类型。
答案 1 :(得分:4)
这里的问题是你使用泛型,然后提取泛型类型值的属性。
泛型允许您执行在运行时填充的一些元编码(实际上是JIT时间)但是对泛型的调用在编译时处理泛型推理。因此,因为您使用PrintProperties
类型的变量调用BaseClass
,所以T
始终推断为BaseClass
,不实际的运行时类型
有两种解决方法 - 一种方法是使用每个 GetType()
的内置object
方法。
var type = entity.GetType();
因为这个garunantees你将有运行时类型。
另一方面,对于需要完美泛型的其他情况,是使用dynamic
对象传递给泛型方法,这允许运行时在运行时推断泛型类型从而获得完全匹配的类型:
static void SomeMethod(BaseClass baseClass)
{
PrintProperties((dynamic)baseClass);
}
答案 2 :(得分:0)
typeof(T)
将返回该特定类型。这意味着当T
为BaseClass
时,您只会获得与其相关的属性。它不知道任何派生的东西。
您要做的是将typeof(T)
替换为entity.GetType()
。 GetType()
返回对象实例的实际类型。