【问题标题】:Get value of static field via dynamic method通过动态方法获取静态字段的值
【发布时间】:2012-07-12 09:38:45
【问题描述】:

我有以下课程:

public class TestClass
{   
    public static readonly string HELLO = "Hello, ";

    public static string SayHello(string name)
    {
        return HELLO + name;
    } 
}

我想通过 DynamicMethod 访问 HELLO 的静态字段。 使用 GetValue 进行标准反射:

public static string GetViaInvoke()
    {
        Type tcType = typeof(TestClass);
        FieldInfo fi = tcType.GetField("HELLO");
        string result = fi.GetValue(null) as string;
        return result;
    }

但我需要类似的东西(OpCodes 来自类似方法的 ILDasm):

public static string GetViaDynamicMethod()
    {
        Type tcType = typeof(TestClass);
        FieldInfo fi = tcType.GetField("HELLO");

        DynamicMethod dm = new DynamicMethod("getHello", typeof(string), Type.EmptyTypes);            
        ILGenerator iL = dm.GetILGenerator();

        iL.DeclareLocal(typeof(string));
        iL.Emit(OpCodes.Nop);
        iL.Emit(OpCodes.Ldsfld, fi);
        iL.Emit(OpCodes.Stloc_0);
        iL.Emit(OpCodes.Br_S, 0x09);
        iL.Emit(OpCodes.Ldloc_0);
        iL.Emit(OpCodes.Ret);

        Func<string> fun = dm.CreateDelegate(typeof(Func<string>)) as Func<string>;
        string result = fun();
        return result;
    }

这个想法非常简单,动态方法适用于非静态字段(ldfld 操作码和 this 对象),但是当我尝试访问静态字段时,我收到异常:

System.InvalidProgramException was unhandled
  Message=InvalidProgramException

【问题讨论】:

    标签: c# windows-phone-7 reflection static dynamicmethod


    【解决方案1】:

    将您编写的 IL 代码建立在具有相同功能的反编译代码上是个好主意,但您仍然需要了解自己在做什么。

    如果您查看the documentation for Br_S,您会发现您应该将它与Label 一起使用,而不是int。我认为您代码中的Br_S 分支到字节偏移量 9 处的指令,但我不知道那是哪条指令,您永远不应该编写这样的代码。

    如果你只是想加载静态字段的值并返回它,你不需要任何局部变量或分支。以下就足够了:

    iL.Emit(OpCodes.Ldsfld, fi);
    iL.Emit(OpCodes.Ret);
    

    它的作用是将值加载到评估堆栈上,然后立即返回。它有效,因为当您从一个确实返回值的方法返回时,评估堆栈上的单个值将用作该返回值。

    【讨论】:

    • 谢谢它的工作。这是我的第一个想法,但它在我的场景中不起作用,这就是我使用 ildasm 和上面的代码的原因。 br_s 的用法很好,你有两种变体,一种:2B int8 > 跳转到指定偏移处的目标指令,短格式,第二种:ILGenerator.Emit(OpCode, Label ) 但是在这种情况下,绝对不能使用它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-28
    • 2019-06-10
    • 2013-11-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多