简体   繁体   中英

How can I get the properties of an inherited object when the parameter is declared as a base type?

I have a simple program that uses reflection to print out the properties and values of the supplied 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("");
    }
}

The problem is that it only prints out the BaseClass properties because I am using generics and passing in the BaseClass into the PrintProperties method.

Output:

A: BaseClass

A: BaseClass

How do I access the properties of the Child classes? I would like an output like:

A: BaseClass
Child1Name: Child1

A: BaseClass
Child2Name: Child2

The problem here is that you're using typeof(T) in PrintProperties , but the T in your example is BaseClass because that's the type of the parameter you give it from SomeMethod .

In your example, remove SomeMethod , call the PrintProperties method directly and it'll work.

A simpler way would be to use entity.GetType() instead of typeof(T) . That way, no matter what the generic type is, you'll always get the true type of the object.

The issues here is that you're using generics and then pulling out the properties of the generic type's value.

Generics allow you to do some metacoding that's filled out at runtime (actually JIT-time) however the calls to generics deal with generic inferencing at compile time. Thus, because you call PrintProperties with a variable of type BaseClass , the T is always inferred to be BaseClass , not the actual runtime type.

There are two ways around this - one is to use the built in GetType() method that every object has.

var type = entity.GetType();

As this garunantees you'll have the runtime type to work with.

The other, for further cases of needing a perfect generic, is to pass to the generic method using a dynamic object, which allow the runtime to infer the generic type at runtime and thus get the exactly matching type:

static void SomeMethod(BaseClass baseClass)
{
    PrintProperties((dynamic)baseClass);
}

typeof(T) will return you that specific type. This means when T is BaseClass you are only ever going to get properties related to it. It does not know about anything derived.

What you do instead is replace typeof(T) with entity.GetType() . GetType() returns you the actual type of the object instance.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM