当参数声明为基类型时,如何获取继承对象的属性?

时间:2015-04-17 15:07:54

标签: c# generics reflection

我有一个简单的程序,它使用反射打印出提供的类的属性和值。

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:Child1

     

A:BaseClass
  Child2Name:Child2

3 个答案:

答案 0 :(得分:6)

此处的问题是您在typeof(T)中使用PrintProperties,但示例中的TBaseClass,因为这是您提供的参数类型来自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)将返回该特定类型。这意味着当TBaseClass时,您只会获得与其相关的属性。它不知道任何派生的东西。

您要做的是将typeof(T)替换为entity.GetType()GetType()返回对象实例的实际类型。