Get protected property value of base class using reflection - c#

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.

Related

Why does GetMethod need BindingFlags as mandatory information in order to find methods?

Assuming I have this class with a private method:
public class Test
{
private void Method()
{
}
}
And this code:
var method1 = typeof(Test).GetMethod("Method"); // null
var method2 = typeof(Test).GetMethod("Method", BindingFlags.NonPublic | BindingFlags.Instance); // works!!
var method3 = typeof(Test).GetMethod("Method",BindingFlags.Instance); // null
Why are method1 and method3 null?
Why do I have to be specific with the BindingFlags in order to actually get the method? If it's because I can have multiple methods with the same name then what does the GetMethods exist for?
How specific do I need to be? In this case I needed to add that I'm looking for a non-public & instance method. Since not all of the BindingFlags values are straight forward, how do I know where I need to stop?
The Private modifier means "hide this method from outsiders", so by default GetMethods() returns only the public members.
1.method1 and method3 are null because it is specifically mentioned in this MSDN link that "You must specify Instance or Static along with Public or NonPublic or no members will be returned."
2.For using reflection you must know exactly what you are looking for otherwise you might get the wrong method to invoke.
3.As I already mentioned in No.1 answer, you must at-least specify "Instance or Static along with Public or NonPublic".

Get all properties of current class and base class

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

GetMethod returning null

I have an asp.net web page. This is the class implementing the page:
public partial class _Default : System.Web.UI.Page
{
private readonly string delegateName = "DynamicHandler";
protected void Page_Load(object sender, EventArgs e)
{
EventInfo evClick = btnTest.GetType().GetEvent("Click");
Type tDelegate = evClick.EventHandlerType;
MethodInfo method = this.GetType().GetMethod("DynamicHandler",
BindingFlags.NonPublic | BindingFlags.Instance);
Delegate d = Delegate.CreateDelegate(tDelegate, this, method);
MethodInfo addHandler = evClick.GetAddMethod();
Object[] addHandlerArgs = { d };
addHandler.Invoke(btnTest, addHandlerArgs);
}
private void DynamicHandler(object sender, EventArgs e)
{
throw new NotImplementedException();
}
}
I am trying to hook up an event handler dynamicly. For some reason method remains null and I can't figure out why. I have done this many times before and I can't figure out what I'm missing.
EDIT: I found that this.GetType() returns the type of the page ASP.default_aspx and not the actual type implementing the page. I don't really know how to get around this...
For the benefit of anyone else, GetMethod() can also return null if the arguments you passed do not match the arguments of the method you are trying to find. So, for example, if you are trying to find the method:
SomeMethod(int intParam, string stringParam)
You need to pass the parameter types to GetMethod:
type.GetMethod("SomeMethod", new[] { typeof(int), typeof(string) });
Or, if you want to specify special binding flags:
type.GetMethod("SomeMethod", BindingFlags.NonPublic | BindingFlags.Instance, null, new[] { typeof(int), typeof(string) }, null);
As you've discovered in your edit, the actually ASPX page gets compiled into a class that inherits from _Default (where your code is located). So you need to make DynamicHandler (at least) protected rather than private.
Specify BindingFlags.FlattenHierarchy also:
this.GetType().GetMethod("DynamicHandler",
BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.FlattenHierarchy);
There are two things to be aware of.
(1) When you use:
this.GetType()
or equivalently just GetType(), the type which is returned is the actual run-time type of the actual instance. Since _Default is a non-sealed class, that type might very well be a more derived (more specialized type) than _Default, i.e. some class which has _Default as its direct or indirect base class.
If what you want is always the "constant" type _Default, use the typeof keyword, so use:
typeof(_Default)
instead of GetType(). This alone would solve your problem.
(2) Even if you specify BindingFlags.NonPublic, inherited private members are not returned. With your choice of binding flags, private methods declared in the same class (the derived class) are returned, but private methods inherited from base classes are not returned. However with internal and protected members, both the ones declared in the class itself and the ones declared in the base classes are returned.
This might make some sense, since a private method is not meant to be invoked from a derived class.
Changing the access level of your DynamicHandler method from private to e.g. protected (as suggested in the other answer) would be enough to solve your problem, as inherited protected members are selected when you use BindingFlags.NonPublic.
It is still interesting that you can't get the inherited private members with BindingFlags. Related thread C#: Accessing Inherited Private Instance Members Through Reflection. It is possible to write a method that searches all base types, of course, like:
static MethodInfo GetPrivateMethod(Type type, string name)
{
MethodInfo retVal;
do
{
retVal = type.GetMethod(name, BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static);
if (retVal != (object)null)
break;
type = type.BaseType;
} while (type != (object)null);
return retVal;
}
That alone would also have solved your problem.

GetFields of derived type

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.

in C#, Is there anyway to determine a class's members at runtime?

Suppose I have a class named foo, and it has 3 public members foo1, foo2, and foo3.
Now suppose I'm writing a function that takes an instance of class foo as a parameter, but when I'm writing this function I have no idea what public members it has.
Is there a way for me to determine at run-time that it has public members foo1, foo2, foo3 AND ONLY foo1, foo2, foo3. IE - find out what all the public members are?
And can I also determine their types?
Well, that's what Reflection is there for :
Type myObjectType = typeof(foo);
System.Reflection.FieldInfo[] fieldInfo = myObjectType.GetFields();
foreach (System.Reflection.FieldInfo info in fieldInfo)
Console.WriteLine(info.Name); // or whatever you desire to do with it
You could use reflection:
// List all public properties for the given type
PropertyInfo[] properties = foo.GetType().GetProperties();
foreach (var property in properties)
{
string propertyName = property.Name;
}
You should be aware that there could be an additional overhead when using reflection because types are evaluated at runtime.
Have a look at the .net reflection namespace:
http://msdn.microsoft.com/en-us/library/ms173183(VS.80).aspx
This is a job for reflection. Look into methods like:
myFoo.GetType().GetMethods(BindingFlags.Instance | BindingFlags.Public);
This will return all public, instance methods that the type has. You can then look through the returned results and determine if this class meets your criteria. There are equivalent methods as well for other types of members, such as GetFields(...), GetProperties(...), etc.
Basically you want to get to know the Type class, which is the core of C#'s reflection capabilities.
foreach(PropertyInfo pi in yourObject.GetType().GetProperties())
{
Type theType = pi.PropertyType;
}
Following article on MSDN should help you determine the methods of a type

Categories