【问题标题】:C# Reflection: Changing private fields of a class with static object reference? [closed]C# 反射:使用静态对象引用更改类的私有字段? [关闭]
【发布时间】:2020-05-01 06:58:19
【问题描述】:

我有一个非常具体的案例,我在 StackOverflow 上阅读了大量关于设置和获取类的私有字段和属性的问题,但它们似乎都不起作用。

我正在通过使用 Harmony(在运行时注入代码的库)注入代码来修改 Unity 游戏。我成功地更改了很多东西,但是一旦值是私有的,我就碰壁了,因为我无法访问或更改值。

使用 dnSpy 检查代码时: 所以有一个公共类 World {},它包含字段 public static World inst 以及两个私有字段 private int GridWidth 和 private int GridHeight。 它还包含属性 GridWidth 和 Gridheight,它们都是公共的,但只有一个 Getter。它包含更多在这里无关紧要的字段。 World.inst 在私有 void Awake() 方法中设置,这是一个特定的 Unity 方法。

简而言之:

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;
    }
  }
}

现在我尝试从外部更改 GridWidth 和 GridHeight 的值,但失败了。我无法更改这部分代码。

在 dnSpy 中,这两个字段被引用(当悬停在字段上时)为 World.GridWidth 和 World.GridHeight 但它们明确设置为 World.inst.GridWidth 和 GridHeight。

我当前的代码是

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

但这不起作用。我还没有真正使用 Reflection,这可能是我犯了一个非常明显的错误,如果是这样,我很抱歉。

我很困惑,非常感谢任何帮助和深入的解释。

【问题讨论】:

  • 该字段的名称似乎是gridWidth(小写),尽管您定义的其他部分与此不一致。
  • @JeroenMostert 你是绝对正确的。想象一下,试图找到一个解决方案 5 个多小时,在堆栈溢出上浪费其他人的时间,才意识到这是一个错字.. 对不起!
  • 另外,你为什么要使用反射来访问你控制的类?为什么不公开这些属性?
  • @Draco18snolongertrustsSE 因为我在运行时修改了编译为汇编文件的外部代码。
  • 好吧,你可以想象在不到 5 小时的时间内调试 typeof(World).GetFields(BindingFlags.Instance | BindingFlags.NonPublic) 来验证你的假设,但还有更糟糕的事情......

标签: c# unity3d reflection game-development dnspy


【解决方案1】:

首先,我认为以下是一个错字

 private int GridWidth;
 private int GridHeight;

上面应该是

  private int gridWidth;
  private int gridHeight;

这是因为您已经有一个同名的公共只读属性,它在内部引用私有变量 - gridWidth 和 gridHeight。

现在,要更改变量,您需要使用gridWidth 来引用该字段:

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

【讨论】:

  • 非常感谢。这只是一个错字。我可能过于关注整个反射的事情,而没有注意细节。谢谢。
  • 请不要回答离题的问题,例如由拼写错误引起的问题
  • @AnuViswan 有什么变化? Asker 在他们的问题中使用了BindingFlags.Instance | BindingFlags.NonPublic。据我所知,这不是他们问题的原因。
猜你喜欢
  • 2011-03-19
  • 2012-06-26
  • 2014-10-13
  • 1970-01-01
  • 2015-04-12
  • 1970-01-01
  • 2011-02-02
相关资源
最近更新 更多