Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Set private setter on property via reflection

I know this has several canonical answers (that I've used successfully in the past!) See https://stackoverflow.com/a/1778410/1675729 and https://stackoverflow.com/a/1565766/1675729. For reference, these methods involve using the SetValue method on the PropertyInfo of the property, or otherwise invoking the setter method with reflection, or in extreme cases, setting the backing field directly. However, none of these methods seem to be working for me now, and I'm curious if something has changed that has broken this functionality.

Consider the following:

using System;
using System.Reflection;

public class Program
{
    public static void Main()
    {
        var exampleInstance = new Example();
        var exampleType = typeof(Example);
        var fooProperty = exampleType.GetProperty("Foo"); // this works fine - the "GetSetMethod" method returns null, however

        // fails with the following:
        // [System.MethodAccessException: Attempt by method 'Program.Main()' to access method 'Example.set_Foo(Int32)' failed.]
        //fooProperty.SetValue(exampleInstance, 24);

        // same error here:
        //Run-time exception (line 14): Attempt by method 'Program.Main()' to access method 'Example.set_Foo(Int32)' failed.
        //exampleType.InvokeMember(fooProperty.Name, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.SetProperty | BindingFlags.Instance, null, exampleInstance, new object[] { 24 });
    }
}

public class Example 
{
    public int Foo { get; private set; }
}

The Foo property has a setter, it's just private. It also fails if I change the setter to protected, which seems even more bizarre, since it's no longer the C#6 initializer-only setter. This fails with both .NET 4.5 and .NET Core 2 as the runtime. What am I missing?

like image 461
NWard Avatar asked Feb 14 '18 16:02

NWard


2 Answers

I was having a similar issue (with the exception that I'm using a static property) and I was able to invoke private setter like this:

public static class Example 
{
    public static int Foo { get; private set; }
}

typeof(Example).GetProperty("Foo").SetMethod.Invoke(null, new object[] { 42});

Haven't tested with non-static though.

like image 112
Alex from Jitbit Avatar answered Sep 22 '22 23:09

Alex from Jitbit


This behaviour is by design. There are some strict rules that govern the ability to abuse reflection in this way.

Accessing Members That Are Normally Inaccessible

In fact if you plan on using reflection at all, in a real life secnario the entire article might be worth a read. Security Considerations for Reflection

like image 27
user6144226 Avatar answered Sep 23 '22 23:09

user6144226