简体   繁体   English

c#system.reflection.emit ldfld

[英]c# system.reflection.emit ldfld

Hi i wrote the following code: 您好我写了以下代码:

     AssemblyName assemblyName = new AssemblyName("SamAsm");
        AssemblyBuilder assemblyBuilder = Thread.GetDomain().DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
        TypeBuilder typeBuilder = assemblyBuilder.DefineDynamicModule("SamAsm.exe").DefineType("SamAsmType", TypeAttributes.Public);
        MethodBuilder methodBuilder1 = typeBuilder.DefineMethod("Main", MethodAttributes.Static | MethodAttributes.Public, typeof(void), new Type[] { typeof(string) });
        ILGenerator gen = methodBuilder1.GetILGenerator();
        FieldInfo field1 = typeof(Form1).GetField("TextBox1", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);

        MethodInfo method2 = typeof(Control).GetProperty("Text", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).GetGetMethod();
        MethodInfo method3 = typeof(String).GetMethod(
            "op_Equality",
            BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic,
            null,
            new Type[]{
    typeof(String),
    typeof(String)
    },
            null
            );
        MethodInfo method4 = typeof(MessageBox).GetMethod(
            "Show",
            BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic,
            null,
            new Type[]{
    typeof(String)
    },
            null
            );



        LocalBuilder a = gen.DeclareLocal(typeof(Boolean));

        System.Reflection.Emit.Label label42 = gen.DefineLabel();

        gen.Emit(OpCodes.Nop);
        gen.Emit(OpCodes.Ldarg_0);
        gen.Emit(OpCodes.Ldfld, field1);
        gen.Emit(OpCodes.Callvirt, method2);
        gen.Emit(OpCodes.Ldstr, "HI");
        gen.Emit(OpCodes.Call, method3);
        gen.Emit(OpCodes.Ldc_I4_0);
        gen.Emit(OpCodes.Ceq);
        gen.Emit(OpCodes.Stloc_0);
        gen.Emit(OpCodes.Ldloc_0);
        gen.Emit(OpCodes.Brtrue_S, label42);
        gen.Emit(OpCodes.Nop);
        gen.Emit(OpCodes.Ldstr, "You cracked me");
        gen.Emit(OpCodes.Call, method4);
        gen.Emit(OpCodes.Pop);
        gen.Emit(OpCodes.Nop);
        gen.MarkLabel(label42);
        gen.Emit(OpCodes.Ret);




        typeBuilder.CreateType().GetMethod("Main").Invoke(null, new string[] { null });
        assemblyBuilder.SetEntryPoint(methodBuilder1, PEFileKinds.WindowApplication);}

When i try this, it stops me on gen.Emit(OpCodes.Ldfld,typeof(Form1).GetField("TextBox1", BindingFlags.Public | BindingFlags.NonPublic)); 当我尝试这个时,它会阻止我在gen.Emit(OpCodes.Ldfld,typeof(Form1).GetField(“TextBox1”,BindingFlags.Public | BindingFlags.NonPublic));

and tell: The value can't be null. 并告诉:该值不能为空。 Parameter name : con . 参数名称:con。 Someone can help me? 有人可以帮帮我吗?

It seems very likely here that the following is returning null : 这里似乎很可能以下是返回null

typeof(Form1).GetField("TextBox1", BindingFlags.Public | BindingFlags.NonPublic)

My immediate guess would be that you need to add a BindingFlags.Instance to the set of flags for it to return the field. 我的直接猜测是你需要在一组标志中添加一个BindingFlags.Instance来返回该字段。

It means that one of the parameters for the call is null, most likely the return value of typeof(Form1).GetField("TextBox1", BindingFlags.Public | BindingFlags.NonPublic) . 这意味着调用的其中一个参数为null,很可能是typeof(Form1).GetField(“TextBox1”,BindingFlags.Public | BindingFlags.NonPublic)的返回值。

Since you already stored that value in the variable field1 , you should go into Debug mode and check that it is not null. 由于您已将该值存储在变量field1中 ,因此应进入调试模式并检查它是否为空。

If the value is null, it can mean different things : 如果值为null,则表示不同的含义:

  • Is there really a field called TextBox1 in your Form1 class ? 在Form1类中是否真的有一个名为TextBox1的字段? Always doubnle-check the spelling, and also character casing. 总是怀疑 - 检查拼写,还有字符套管。 Reflection methods like GetField, GetProperty... are case sensitive unless used with BindingFlags.IgnoreCase. 除非与BindingFlags.IgnoreCase一起使用,否则GetField,GetProperty等反射方法区分大小写。
  • Is it accessible using the value of BindingFlags you provided (eg. is it static ?) ? 是否可以使用您提供的BindingFlags值来访问它(例如,它是静态的吗?)?

In your case, if you look at the MSDN documentation for GetField, it explicitely states : 在您的情况下,如果您查看GetField的MSDN文档 ,它明确指出:

The following BindingFlags filter flags can be used to define which fields to include in the search: 以下BindingFlags过滤器标志可用于定义要包含在搜索中的字段:

You must specify either BindingFlags.Instance or BindingFlags.Static in order to get a return . 您必须指定BindingFlags.Instance或BindingFlags.Static才能获得返回

Specify BindingFlags.Public to include public fields in the search. 指定BindingFlags.Public以在搜索中包含公共字段。

Specify BindingFlags.NonPublic to include non-public fields (that is, private, internal, and protected fields) in the search. 指定BindingFlags.NonPublic以在搜索中包含非公共字段(即私有,内部和受保护字段)。

Specify BindingFlags.FlattenHierarchy to include public and protected static members up the hierarchy; 指定BindingFlags.FlattenHierarchy以在层次结构中包含公共和受保护的静态成员; private static members in inherited classes are not included. 不包括继承类中的私有静态成员。

So you should use BindingFlags.Public | 所以你应该使用BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.NonPublic | BindingFlags.Instance instead of BindingFlags.Public | BindingFlags.Instance而不是BindingFlags.Public | BindingFlags.NonPublic BindingFlags.NonPublic

Also replace 也替换

gen.Emit(OpCodes.Ldfld,typeof(Form1).GetField("TextBox1", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance));

With

gen.Emit(OpCodes.Ldfld, field1);

And use the proper flags on the line where you are assigning field1. 并在您指定field1的行上使用正确的标志。

UPDATE : You have the same issue with your final call to Main. 更新 :您对Main的最终调用存在同样的问题。 You need to specify BindingFlags.Static in the following line of code, sinhce you defined your method as static using MethodAttributes earlier in your code : 您需要在以下代码行中指定BindingFlags.Static,而您在代码中使用MethodAttributes将方法定义为静态:

typeBuilder.CreateType().GetMethod("Main", BindingFlags.Static | BindingFlags.Public).Invoke(null, new string[] { null });

Additionnally, you do not want to retrieve property accessors the way you are doing it : instead of using GetMethod with the name of the accessor (get_Text), you should use GetProperty : 另外,您不希望以您的方式检索属性访问器:您应该使用GetProperty而不是将GetMethod与访问者的名称(get_Text)一起使用:

    MethodInfo method2 = typeof(Control).GetProperty("Text", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).GetMethod;

Hope that helps. 希望有所帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM