This article shows how one of the basic OOP principles – encapsulation – can be violated using reflection.
Let’s assume that we have a simple class with a private field called “someHiddenValue”.
class ClassThatHidesSomething { private int someHiddenValue = 5; } |
We want to modify that field from outside the class. This can be done extremely easy through Reflection. First of all we need to get the Type of the ClassThatHidesSomething and get some information about the someHiddenValue field.
Type classThatHidesSomethingType = typeof(ClassThatHidesSomething); FieldInfo field = classThatHidesSomethingType.GetField( "someHiddenValue", BindingFlags.NonPublic | BindingFlags.Instance); |
- BindingFlags.NonPublic specifies that we want to search in all fields; by default it searches only the public fields – actually here is the trick that violates encapsulation.
- BindingFlags.Instance specified that we want to search in instance fields also; by default it searches only in static ones.
Now that we have the FieldInfo of that specific field we can do whatever we want with it. Let’s display its value. But first, because the field is an instance field we need an instance of ClassThatHidesSomething.
ClassThatHidesSomething c = new ClassThatHidesSomething(); int hiddenFieldValue = (int)field.GetValue(c); Console.WriteLine("Hidden field value: {0}", hiddenFieldValue); |
Using the same instance c we can set the private field’s value.
field.SetValue(c, 6); |
Below you can see the entire code (it is a console application):
using System; using System.Reflection; namespace Reflection { class ClassThatHidesSomething { private int someHiddenValue = 5; } class Reflection { const int ANumber = 10; public static void Main(string[] args) { Type classThatHidesSomethingType = typeof(ClassThatHidesSomething); FieldInfo field = classThatHidesSomethingType.GetField( "someHiddenValue", BindingFlags.NonPublic | BindingFlags.Instance); //It is good to check this because //we don't want a NullReferenceException if (field == null) Console.Write("Field not found"); else { ClassThatHidesSomething c = new ClassThatHidesSomething(); int hiddenFieldValue = (int)field.GetValue(c); Console.WriteLine("Hidden field value: {0}", hiddenFieldValue); field.SetValue(c, 6); int newHiddenFiledValue = (int)field.GetValue(c); Console.WriteLine("New hidden field value: {0}", newHiddenFiledValue); } } } } |
The code outputs:
Hidden field value: 5 New hidden field value: 6 |
Ok that one is really cool.
But u can get a list of class private variables? in case you don’t know the class internal variables?
Yes Timotei you can do that by using the “GetFields” method.
I thought only Chuck Norris could do that! :-O
\Remarks
This method will assign value to the field reflected by this instance on object obj. If the field is static, obj will be ignored. For non-static fields, obj should be an instance of a class that inherits or declares the field. The new value is passed as an Object. For example, if the field’s type is Boolean, an instance of Object with the appropriate Boolean value is passed. Before setting the value, SetValue checks to see if the user has access permission. This final method is a convenience method for calling the following SetValue method.
6z33zd7h.alert_note(en-us,VS.90).gifNote:
Fully trusted code has the permissions that are needed to access and invoke private constructors, methods, fields, and properties using reflection.
6z33zd7h.alert_note(en-us,VS.90).gifNote:
Starting with the .NET Framework version 2.0 Service Pack 1, this method can be used to access non-public members if the caller has been granted ReflectionPermission with the ReflectionPermissionFlag..::.RestrictedMemberAccess flag and if the grant set of the non-public members is restricted to the caller’s grant set, or a subset thereof. (See Security Considerations for Reflection.)
To use this functionality, your application should target the .NET Framework version 3.5 . For more information, see .NET Framework 3.5 Architecture . \
http://msdn.microsoft.com/en-us/library/6z33zd7h.aspx