当参数声明为基类型时,如何获取继承对象的属性?
How can I get the properties of an inherited object when the parameter is declared as a base type?
我有一个简单的程序,它使用反射打印出提供的属性和值 class。
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
如何访问子 classes 的属性?我想要这样的输出:
A: BaseClass
Child1Name: Child1
A: BaseClass
Child2Name: Child2
这里的问题是您在 PrintProperties
中使用了 typeof(T)
,但是您示例中的 T
是 BaseClass
,因为这是您的参数类型来自 SomeMethod
.
在您的示例中,删除 SomeMethod
,直接调用 PrintProperties
方法即可。
更简单的方法是使用 entity.GetType()
而不是 typeof(T)
。这样,无论泛型类型是什么,您将始终获得对象的真实类型。
这里的问题是您正在使用泛型,然后提取泛型类型值的属性。
泛型允许您执行一些在运行时(实际上是 JIT 时间)填写的元编码,但是对泛型的调用在编译时处理泛型推理。因此,因为您使用 BaseClass
类型的变量调用 PrintProperties
,所以 T
总是被推断为 BaseClass
, 而不是 实际运行时类型。
有两种解决方法 - 一种是使用 every object
具有的内置 GetType()
方法。
var type = entity.GetType();
作为保证,您将拥有可以使用的运行时类型。
另一种,对于需要完美泛型的其他情况,是使用 dynamic
对象传递给泛型方法,这允许运行时推断泛型类型 在运行时 从而得到完全匹配的类型:
static void SomeMethod(BaseClass baseClass)
{
PrintProperties((dynamic)baseClass);
}
typeof(T)
会 return 你那个特定的类型。这意味着当 T
是 BaseClass
时,您只会获得与其相关的属性。它不知道派生的任何东西。
您要做的是将 typeof(T)
替换为 entity.GetType()
。 GetType()
return你是对象实例的实际类型。
我有一个简单的程序,它使用反射打印出提供的属性和值 class。
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
如何访问子 classes 的属性?我想要这样的输出:
A: BaseClass
Child1Name: Child1A: BaseClass
Child2Name: Child2
这里的问题是您在 PrintProperties
中使用了 typeof(T)
,但是您示例中的 T
是 BaseClass
,因为这是您的参数类型来自 SomeMethod
.
在您的示例中,删除 SomeMethod
,直接调用 PrintProperties
方法即可。
更简单的方法是使用 entity.GetType()
而不是 typeof(T)
。这样,无论泛型类型是什么,您将始终获得对象的真实类型。
这里的问题是您正在使用泛型,然后提取泛型类型值的属性。
泛型允许您执行一些在运行时(实际上是 JIT 时间)填写的元编码,但是对泛型的调用在编译时处理泛型推理。因此,因为您使用 BaseClass
类型的变量调用 PrintProperties
,所以 T
总是被推断为 BaseClass
, 而不是 实际运行时类型。
有两种解决方法 - 一种是使用 every object
具有的内置 GetType()
方法。
var type = entity.GetType();
作为保证,您将拥有可以使用的运行时类型。
另一种,对于需要完美泛型的其他情况,是使用 dynamic
对象传递给泛型方法,这允许运行时推断泛型类型 在运行时 从而得到完全匹配的类型:
static void SomeMethod(BaseClass baseClass)
{
PrintProperties((dynamic)baseClass);
}
typeof(T)
会 return 你那个特定的类型。这意味着当 T
是 BaseClass
时,您只会获得与其相关的属性。它不知道派生的任何东西。
您要做的是将 typeof(T)
替换为 entity.GetType()
。 GetType()
return你是对象实例的实际类型。