So what I have right now is something like this:
PropertyInfo[] info = obj.GetType().GetProperties(BindingFlags.Public);
where obj
is some object.
The problem is some of the properties I want aren't in obj.GetType()
they're in one of the base classes further up. If I stop the debugger and look at obj, the I have to dig through a few "base" entries to see the properties I want to get at. Is there some binding flag I can set to have it return those or do I have to recursively dig through the Type.BaseType
hierarchy and do GetProperties
on all of them?
Use this:
PropertyInfo[] info = obj.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);
EDIT: Of course the correct answer is that of Jay . GetProperties()
without parameters is equivalent to GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static )
. The BindingFlags.FlattenHierarchy
plays no role here.
I don't think it's that complicated.
If you remove the BindingFlags
parameter to GetProperties, I think you get the results you're looking for:
class B
{
public int MyProperty { get; set; }
}
class C : B
{
public string MyProperty2 { get; set; }
}
static void Main(string[] args)
{
PropertyInfo[] info = new C().GetType().GetProperties();
foreach (var pi in info)
{
Console.WriteLine(pi.Name);
}
}
produces
MyProperty2 MyProperty
If you access Type.BaseType
, you can get the base type. You can recursively access each base type and you'll know when you've hit the bottom when your type is System.Object
.
Type type = obj.GetType();
PropertyInfo[] info = type.GetProperties(BindingFlags.Public);
PropertyInfo[] baseProps = type.BaseType.GetProperties(BindingFlags.Public);
I would tend to agree with Nicolas; unless you know you need reflection, then ComponentModel
is a viable alternative, with the advantage that you will get the correct metadata even for runtime models (such as DataView
/ DataRowView
).
For example:
foreach (PropertyDescriptor prop in TypeDescriptor.GetProperties(obj))
{
Console.WriteLine("{0}={1}", prop.Name, prop.GetValue(obj));
}
As an aside, you can also do some simple performance tricks with this; you can do the same with reflection and Delegate.CreateDelegate
, but there is no centralised place to hide the logic away, unlike TypeDescriptor
with a TypeDescriptionProvider
(don't worry if these are unfamiliar; you can just use the code "as is" ;-p).
利用:
TypeDescriptor.GetProperties(obj);
Just to be complete, you can't get PRIVATE fields and properties from base classes this way. You'll have to use a recursive loop for that:
public static IEnumerable<PropertyInfo> GetProperties(Type type, bool forGetter)
{
// Loop over public and protected members
foreach (var item in type.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))
{
yield return item;
}
// Get first base type
type = type.BaseType;
// Find their "private" memebers
while (type != null && type != typeof(object))
{
// Loop over non-public members
foreach (var item in type.GetProperties(BindingFlags.Instance | BindingFlags.NonPublic))
{
// Make sure it's private!
// To prevent doubleing up on protected members
var methodInfo = forGetter ? item.GetGetMethod(true) : item.GetSetMethod(true);
if (methodInfo != null && methodInfo.IsPrivate)
{
yield return item;
}
}
// Get next base type.
type = type.BaseType;
}
}
and
public static IEnumerable<FieldInfo> GetFields(Type type)
{
// Loop over public and protected members
foreach (var item in type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))
{
yield return item;
}
// Get first base type
type = type.BaseType;
// Find their "private" memebers
while (type != null && type != typeof(object))
{
// Loop over non-public members
foreach (var item in type.GetFields(BindingFlags.Instance | BindingFlags.NonPublic))
{
// Make sure it's private!
// To prevent doubleing up on protected members
if (item.IsPrivate)
{
yield return item;
}
}
// Get next base type.
type = type.BaseType;
}
}
Note: you will get PROTECTED fields & properties twice.
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.