I have 2 classes (lets say "BaseItem" and "ChildItem") with several internal properties. In the BaseClass i have defined a method which should read out all of this properties with
PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(this);
or
PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(this.GetType());
When i call this method in an instance of "ChildItem", i get only the properties that are defined in "ChildItem". What can i do to get also the the properties of "BaseItem"?
Regards
Dave
For internal properties (as clarified in the question comments), although not indicated (they're internal for a reason), you can use:
var internalProperties = GetType().GetProperties(
BindingFlags.Instance |
BindingFlags.NonPublic |
BindingFlags.Public));
It's the flag BindingFlags.NonPublic that needs to be applied.
You could just cast it to BaseItem and do GetProperties() separately..
Related
I use this code:
BindingFlags flags= BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public;
PropertyInfo prop = myObj.GetProperty("Age", flags);
prop is not null. However, when I try to get all properties from myObj:
foreach(MemberInfo e in myObj.GetType().GetMembers( flags) ) { //neither GetProperties helps
Console.WriteLine(e.Name);
}
that property (Age) is not listed. I can't understand how this happens.
The dfiference between Type.GetProperty and Type.GetMembers is that both return private properties/members(which include properties), but GetMembers only of this type and not from base types whereas GetProperty also returns private properties of base types.
GetProperty:
Specify BindingFlags.NonPublic to include non-public properties (that
is, private, internal, and protected properties) in the search.
GetMembers:
Specify BindingFlags.NonPublic to include non-public members (that is,
private, internal, and protected members) in the search. Only
protected and internal members on base classes are returned; private
members on base classes are not returned.
So i guess that Age is an inherited property. If you would add BindingFlags.DeclaredOnly the result should be the same, you wouldn't see Age.
If you want to force GetMembers to include also private members of base types, use following extension method that loops all base types:
public static class TypeExtensions
{
public static MemberInfo[] GetMembersInclPrivateBase(this Type t, BindingFlags flags)
{
var memberList = new List<MemberInfo>();
memberList.AddRange(t.GetMembers(flags));
Type currentType = t;
while((currentType = currentType.BaseType) != null)
memberList.AddRange(currentType.GetMembers(flags));
return memberList.ToArray();
}
}
Now your BindingFlags work already and even a private "inherited" Age property is returned:
MemberInfo[] allMembers = myObj.GetType().GetMembersInclPrivateBase(flags);
I would like to know if it is possible to access the value of the ConfigurationId property which is located in the base class of the object and it's private. I have tried to do it with reflection with no luck.
To access ConfigurationId property i have used following code:
SubsetController controller = new SubsetController(new CConfigRepository(new FakeDataContextRepository()));
var myBaseClassProtectedProperty =
controller.GetType().BaseType
.GetProperty("CCITenderInfo", BindingFlags.NonPublic | BindingFlags.Instance)
.GetValue(controller);
var myProtectedProperty =
CCITenderInfo.GetType()
.GetProperty("ConfigurationId", BindingFlags.Public | BindingFlags.Instance)
.GetValue(myBaseClassProtectedProperty);
Assuming the following parent and child class:
class BaseClass
{
private string privateField = "I'm Private";
}
class ChildClass : BaseClass
{
}
You can read privateField's value from a ChildClass instance using reflection like this:
ChildClass childInstance = new ChildClass();
object privateFieldValue = childInstance.GetType().BaseType
.GetField("privateField", BindingFlags.NonPublic | BindingFlags.Instance)
.GetValue(childInstance);
Console.WriteLine(privateFieldValue); // I'm Private
To add to this answer - you should use the Instance and NonPublic binding flags for sure, but you should also ensure that you are actually referencing properties and not fields.
E.g. if you have
protected string Andrew;
You will not be able to get this via GetProperty, no matter what binding flags you use. Why - because it is a field, and not a property...
To fix this, just change it to
protected string Andrew {get;set;}
and then you can use the GetProperty method.
Yes, this is possible with reflection.
However, in order to look up nonpublic members, you'll need to use the reflection overload which take BindingFlags parameters. In order to look up private members, you'll also need to access via the typeof the base class, even when using BindingFlags.FlattenHierarchy. This also means you'll need to use the exact binding, however note that contradictory flags (such as using both NonPublic and Public) are valid and will return either at that point.
Be aware that the very need to look up nonpublic members could be considered code smell, and you should do so very carefully. Also be aware that nonpublic members are not guaranteed to have the same names across different versions.
We are giving some repetitive jobs to a consultant company, we just have a few constraints that could not be checked by compilation, like a requirement to override a specific property in all class implementing a specific interface.
The property of the interface, which should be overrided in all classes has the following signature:
dynamic Definition{get;}
I found this stackoverflow question: How to find out if property is inherited from a base class or declared in derived?
Which is closed to my case, but in my case, the property is defined is inherited class and overrided in this one:
public class ClassA:IMyInterface
{
public virtual dynamic Definition{get{ /*return SomethingSpecificToClassA;*/}}
}
public class ClassB:ClassA
{
public override dynamic Definition{get{ /*return SomethingSpecificToClassB;*/}}
}
//The end goal is to know if ClassB has correctly overriden the property
bool overriden = typeof(ClassB)GetProperties(...).Any(p=>p.Name=="Definition");
This is the solution: you ask ClassB its interface map, you look for the method you want in the interface map and then you look where the implementation method (classMethod) is declared.
var interfaceMethod = typeof(I).GetProperty("Definition").GetGetMethod();
var map = typeof(ClassB).GetInterfaceMap(typeof(I));
var ix = Array.IndexOf(map.InterfaceMethods, interfaceMethod);
var classMethod = map.TargetMethods[ix];
bool isDeclaredInClass = classMethod.DeclaringType == typeof(ClassB);
You can find for property declared only in your type of interests:
var prop = typeof (ClassB).GetProperty("Definition", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);
Then you can then check if its getter is virtual:
prop.GetMethod.IsVirtual
which will be false if Definition hides (or uses new) in ClassB
I am trying to reflect the fields in a derived type but it's returning the fields of the
base type.
public class basetype
{
string basevar;
}
public class derivedtype : basetype
{
string derivedvar;
}
In some function:
derivedtype derived = new derivedtype();
FieldInfo[] fields = derived.GetType().GetFields();
This will return basevar, but not derivedvar. I've tried all the different bindings and it doesn't seem to make a difference.
Also, I'm doing this in ASP.NET within App_Code where basevar is defined in App_Code and derivedvar is a user control defined in App_Controls where the types are not in scope.
As is, this will return nothing as the default binding is for public fields only.
As is also, derivedtype isn't derived from basetype
With:
FieldInfo[] fields = derived.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Instance);
It returns derivedvar. I've just checked in LINQPad.
If I change derivedtype to be derived from basetype, then I can get both fields with:
FieldInfo[] fields = derived.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Instance).Concat(derived.GetType().BaseType.GetFields(BindingFlags.NonPublic | BindingFlags.Instance)).ToArray();
Reflection is a bit odd.
If the members are public, all of them up the entire hierarchy are visible.
If the members are non-public, you have to specify BindingFlags.NonPublic and you will only get those members that are of the type used. Inherited members are not visible. If you want to see all the non-public members of a type you'll have to walk up the inheritence chain.
I am given:
A class "T" which implements properties that are decorated with Attributes that I am interested in.
A PropertyInfo "p" representing a property belonging to (1) an interface "I" that T implements, (2) a base class "B" that T inherits from, or (3) the class T itself.
I need to get the Attributes defined on (or inherited by) the properties in T, even if p's DeclaringType is an interface that T implements or a class that T inherits from. So I need a way to get from p to the PropertyInfo that actually exists on T. Thus it seems that there are 3 cases:
p.DeclaringType == typeof(T)
This is the trivial case. I can iterate through T's properties until I find the match. Example:
return typeof(T).GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
.FirstOrDefault(property => property == p)
p.DeclaringType == typeof(I) where I is an interface that T implements
This is more complicated. I found that I can use an InterfaceMapping to find the corresponding implementation of the p in T. It seems kind of hackish, but here what works:
if (p.DeclaringType.IsInterface &&
typeof(T).GetInterfaces().Contains(p.DeclaringType))
{
InterfaceMapping map = typeof(T).GetInterfaceMap(p.DeclaringType);
MethodInfo getMethod = p.GetGetMethod();
for (int i = 0; i < map.InterfaceMethods.Length; i++)
{
if (map.InterfaceMethods[i] == getMethod)
{
MethodInfo target = map.TargetMethods[i];
return typeof(T).GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
.FirstOrDefault(property => property.GetGetMethod() == target);
}
}
}
p.DeclaringType == typeof(B) where B is a class that T inherits from
I have not yet been able to figure out how to identify the property on T that overrides a virtual property p defined in Ts base class B.
So my questions are
In case 3 how do I find the PropertyInfo on T that overrides the property p on B?
Is there a better way to do all three? Perhaps a way to unify the three cases.
I think you're missing a case : it is possible that T just inherits the property from B, without overriding it (unless you know for sure this won't happen in your specific scenario).
Anyway, you just need to search the property by name, using typeof(T).GetProperty, since there can't be 2 properties with the same name in a given class (unlike methods, which can have several overloads). However, you need to watch out for the case where T hides the property inherited from B, using the new modifier. To handle that case, you can check the Attributes of the property's getter method (obtained with GetGetMethod) : if the NewSlot flag is present, it hides the inherited getter.
I found a way to answer case 3. The key is MethodInfo.GetBaseDefinition
if (typeof(T).IsSubclassOf(p.DeclaringType))
{
MethodInfo baseDefinition = p.GetGetMethod().GetBaseDefinition();
return typeof(T).GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
.FirstOrDefault(property => property.GetGetMethod().GetBaseDefinition() == baseDefinition);
}
However this only works for properties that have been overridden on T.
Edit:
By comparing the following, it doesn't matter if the properties have or haven't been overriden on T:
property.GetGetMethod().GetBaseDefinition().MetadataToken == baseDefinition.MetadataToken