Getting a private variable through Reflection?

D

David Veeneman

I need to get a parent's private variable from within a control. Here's what
I'm doing: I have a control that I want to be able to detect the presence of
a particular (System.ComponentModel) component on the same form. Components
aren't contained in the Form.Controls collection--they are contained in a
private Designer variable called 'components'. So, to detect the component,
I'm going to need to get to that private variable from the control's parent
form.

Does anyone have any sample code to get a private variable from a parent?
I'm new to Reflection, and I'm struggling a bit to sort it out. Thanks.
 
M

Marina Levit [MVP]

Yes, the way it declares 'components' as a local variable is a major pain. I
have no idea why this was done - it makes inheritance a big pain when you
want the base class to do something with the components.

I don't know of a way to get the private variable using reflection.

What I had to do, was define an overridable property, and then the developer
of the inherited class has to override it, and return 'components'. That
way the base class can call the property, and polymorphically, the overriden
version will get called, thus getting the components.
 
D

David Veeneman

get a parent's private variable from within a control.
You use GetField().

Thanks, Alan-- Here's what I've got.

Type parentForm = this.Parent.GetType();
FieldInfo fieldInfo = parentForm.GetField("components",
BindingFlags.Instance |
BindingFlags.NonPublic);
object fieldData = fieldInfo.GetValue(components);

The GetField() works, but the GetValue() fails. Here's the error I get:

Field 'components' defined on type 'MyApp.FormMain1' is not a field on the
target object which is of type 'System.ComponentModel.Container'.

Any idea what I'm missing? Thanks again.
 
D

David Veeneman

Here's the code for a control to iterate through the System.ComponentModel
components of its parent:

// Get the parent's components collection
Type parentForm = this.Parent.GetType();
FieldInfo fieldInfo = parentForm.GetField("components",
BindingFlags.Instance |
BindingFlags.NonPublic);
IContainer parent = (IContainer)fieldInfo.GetValue(this.Parent);

// Check for a helper component
foreach (Component component in parent.Components)
{
if (component.GetType() == typeof(MyHelperComponent))
{
m_Helper = (MyHelperComponent)component;
}
}

Thanks again to Alan Pretre for his help.
 
A

Alan Pretre

David Veeneman said:
Here's the code for a control to iterate through the System.ComponentModel
components of its parent:

Note that in general it is unsafe to access private members of a class due
to the fact that future changes might be made to the thing you're prying
into. I got bit by this once with the switch from the .NET framework 1.x to
2.0. Was prying into something, which then disappeared in the later
release.

-- Alan
 
D

David Veeneman

Note that in general it is unsafe to access private members of a class due
to the fact that future changes might be made to the thing you're prying
into.

Thanks--point well taken. I don't have a lot of experience with reflection
because I avoid it like the plague, for the very reasons you point out.

Private variables are private for a reason, and one normally ought not go
poking around where not invited. In this case, it was literally the only way
to do what needed to be done.

What I can't figure out is, what's the rationale behind putting the
components collection in a private Designer variable, when the controls
collection is a property of the Form class?
 
G

Guest

David Veeneman said:
I need to get a parent's private variable from within a control. Here's what
I'm doing: I have a control that I want to be able to detect the presence of
a particular (System.ComponentModel) component on the same form. Components
aren't contained in the Form.Controls collection--they are contained in a
private Designer variable called 'components'. So, to detect the component,
I'm going to need to get to that private variable from the control's parent
form.

If you are trying to read private members via Reflection, that's a good sign
you should probably look for another solution. ;-) Breaking encapsulation
in an object-oriented language like C# is just asking for trouble.

Luckily, .NET made it easy to access all components on a form through public
properties. Following is an excellent article that explains how design-time
development works:

http://www.awprofessional.com/articles/article.asp?p=169528&seqNum=2&rl=1

Specifically, here is a diagram that shows the relationship between a
control/form and all the controls and components on that form:

http://www.awprofessional.com/content/images/chap9_0321116208/elementLinks/09fig05.gif
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top