54

Why is the following code not working:

class Program { static void Main ( string[ ] args ) { SomeClass s = new SomeClass( ); s.GetType( ).GetField( "id" , System.Reflection.BindingFlags.NonPublic ) // sorry reasently updated to GetField from GetProperty... .SetValue( s , "new value" ); } } class SomeClass { object id; public object Id { get { return id; } } } 

I am trying to set the value of a private field.


Here is the exeption I get:

 System.NullReferenceException was unhandled Message=Object reference not set to an instance of an object. Source=ConsoleApplication7 StackTrace: at Program.Main(String[] args) in C:\Users\Antonio\Desktop\ConsoleApplication7\ConsoleApplication7\Program.cs:line 18 at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args) at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args) at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly() at System.Threading.ThreadHelper.ThreadStart_Context(Object state) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) at System.Threading.ThreadHelper.ThreadStart() InnerException: 
2
  • Could you specify "not working"? What happens, and how does that differ from what you expect? Do you get any error message? Commented Oct 21, 2012 at 0:48
  • Try itterating through GetFields() (manually using debugger breakpoint) to see what is returned. Afaik, there is no guarantee that the variable id will stay named id, but I'm not sure. Also, I've had problems getting private properties/methods before, and it's generally solved by using BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance (for instance) Commented Oct 21, 2012 at 0:55

4 Answers 4

115

Try this (inspired by Find a private field with Reflection?):

var prop = s.GetType().GetField("id", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); prop.SetValue(s, "new value"); 

My changes were to use the GetField method - you are accessing a field and not a property, and to or NonPublic with Instance.

Sign up to request clarification or add additional context in comments.

2 Comments

unfortunately this doesn't work for structures. it seams to set value of structure copy sent to SetValue, and original structure remains unchanged.
According to Jon Skeet, the correct way to set a struct requires explicit boxing before calling SetValue: stackoverflow.com/questions/6280506/…
2

If you want a faster alternative consider using expression trees or Unsafe.As<T>. In testing reflection can be anywhere between 30x to 100x times slower than either technique.

Expression tree

static Action<TSource, TArg> BuildSetterExpression<TSource, TArg>(FieldInfo field) { var inputObject = Expression.Parameter(typeof(TSource)); var valueToSet = Expression.Parameter(typeof(TArg)); var fieldInformation = Expression.Field(inputObject, field); var fieldAssignment = Expression.Assign(fieldInformation, valueToSet); return Expression.Lambda<Action<TSource, TArg>>(fieldAssignment, inputObject, valueToSet).Compile(); } var fieldInfo = typeof(MyClass).GetField("_num", BindingFlags.NonPublic | BindingFlags.Instance); var setNumFunc = BuildSetterExpression<MyClass, int>(fieldInfo); var instance = new MyClass(); setNumFunc(instance, 123); Assert.Equal(123, instance.Num); class MyClass { private int _num = 12; public int Num => _num; } 

Unsafe.As<T>

If you know the structure of the object you're accessing and don't mind using unsafe code use Unsafe.As<T>

var source = new SourceClass(); var target = Unsafe.As<TargetClass>(source); target.Num = 123; Assert.Equal(123, source.GetPrivateNum); class SourceClass { private int _num = 12; public int GetPrivateNum => _num; } class TargetClass { public int Num { get; set; } } 

Comments

1

Evidently, adding BindingFlags.Instance seems to have solved it:

> class SomeClass { object id; public object Id { get { return id; } } } > var t = typeof(SomeClass) ; > t [Submission#1+SomeClass] > t.GetField("id") null > t.GetField("id", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); > t.GetField("id", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance) [System.Object id] > 

Comments

0

Extending Nick's answer, I wrote a static method that sets a private field for a given T class:

 public static void SetPrivateField<T, T2>(this T item, string fieldName, T2 newValue) { var field = item.GetType().GetField(fieldName, BindingFlags.NonPublic | BindingFlags.Instance); field.SetValue(item, newValue); } 

To use this:

someClassInstance.SetPrivateField("id", "newValue"); // realizes the type T2 by the fact "newValue" is a string. // probably doesn't work on readonly, haven't tried. 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.