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: 24 Answers
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.
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; } } 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] > Extending Nick's answer:
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.