-1

I got a very specific case and I read tons of questions on StackOverflow about setting and getting private fields and properties of classes but they all do not seem to work.

I am modding a Unity game by injecting code with Harmony ( a library to inject code at runtime). I successfully changed a lot of things but as soon as values are private, I hit a wall since I cannot access nor change the values.

When inspecting the code with dnSpy: So there is the public class World {} which contains the field public static World inst as well as two private fields private int GridWidth and private int GridHeight. It also contains the properties GridWidth and Gridheight, both public but only with a Getter. It contains further fields which do not matter here. World.inst gets set in the private void Awake() method, a specific Unity method.

In short:

public class World : MonoBehaviour 
{
  public static World inst;

  private void Awake()
  {
    World.inst = this;
    this.gridWidth = 55;
    this.gridHeight = 55;
  }

  private int GridWidth;
  private int GridHeight;

  public int GridWidth
  {
    get
    {
        return this.gridWidth;
    }
  }

  public int GridHeight
  {
    get
    {
        return this.gridHeight;
    }
  }
}

Now I tried to change the values of GridWidth and GridHeight externally but failed. I cannot change this part of the code.

In dnSpy, the two fields are referrenced ( when hovering over the fields) as World.GridWidth and World.GridHeight but they are clearly set as World.inst.GridWidth and GridHeight.

My current code is

  var WorldField = typeof(World).GetField("GridWidth", BindingFlags.Instance | BindingFlags.NonPublic);
  WorldField.SetValue(World.inst, 100);

But this does not work. I haven't really worked with Reflection yet and it might be that I am making a really obvious mistake, if so, I am very sorry.

I am very confused and any help and indepth Explanation is very appreciated.

  • 1
    The field's name appears to be `gridWidth` (lower case), although other parts of your definition are not consistent with this. – Jeroen Mostert Jan 14 '20 at 14:32
  • @JeroenMostert You are absolutely right. Imagine, trying to find a solution for 5+ hours, wasting the time of other people on stack overflow, just to realise that it was a typo.. I feel sorry! – Cedric Jansen Jan 14 '20 at 14:38
  • Also, why are you using reflection to access a class you control? Why not make those properties public? – Draco18s no longer trusts SE Jan 14 '20 at 14:42
  • @Draco18snolongertrustsSE Since I am modding foreign code at runtime that is compiled as assembly file. – Cedric Jansen Jan 14 '20 at 14:43
  • Well, you conceivably could have debugged `typeof(World).GetFields(BindingFlags.Instance | BindingFlags.NonPublic)` to verify your assumptions in less than 5 hours, but there's worse things... – Jeroen Mostert Jan 14 '20 at 14:43
  • Stack overflow asks that questions about debugging include a [mre]. Note that making an MRE will help find typo errors like this. Please keep that in mind and do your best to include an MRE in your next question. – Ruzihm Jan 14 '20 at 17:13

1 Answers1

0

To begin with, I believe following was a typo

 private int GridWidth;
 private int GridHeight;

Above was supposed to be

  private int gridWidth;
  private int gridHeight;

This is because you already have a public readonly property with the same name, which internally refers to the private variables - gridWidth & gridHeight.

Now, for change the variable, you need to use gridWidth to refer to the field:

var WorldField = typeof(World).GetField("gridWidth", BindingFlags.Instance | BindingFlags.NonPublic);
WorldField.SetValue(World.inst, 100);
Ruzihm
  • 19,749
  • 5
  • 36
  • 48
Anu Viswan
  • 17,797
  • 2
  • 22
  • 51
  • 1
    Thank you very much. It was just a typo.. I probably focused on the whole reflection thing too much and did not pay attention to the details. Thanks. – Cedric Jansen Jan 14 '20 at 14:39
  • Please don't answer questions that are off topic, such as those caused by a typo – Ruzihm Jan 14 '20 at 16:07
  • @AnuViswan what change? Asker used `BindingFlags.Instance | BindingFlags.NonPublic` in their question. As far as I can tell, that was not a cause of their problem. – Ruzihm Jan 14 '20 at 16:38