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: Child1A: 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.