1

嗨,我写了以下代码:

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

当我尝试这个时,它阻止了我 gen.Emit(OpCodes.Ldfld,typeof(Form1).GetField("TextBox1", BindingFlags.Public | BindingFlags.NonPublic));

并告诉:该值不能为空。参数名称:con。有人可以帮助我吗?

4

2 回答 2

2

这里似乎很可能会返回以下内容null

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

我的直接猜测是您需要在BindingFlags.Instance标志集中添加 a 才能返回该字段。

于 2012-12-10T12:12:02.293 回答
2

这意味着调用的参数之一为空,很可能是typeof(Form1).GetField("TextBox1", BindingFlags.Public | BindingFlags.NonPublic)的返回值。

由于您已经将该值存储在变量field1中,您应该进入调试模式并检查它是否不为空。

如果该值为空,则可能意味着不同的事情:

  • 您的 Form1 类中真的有一个名为 TextBox1 的字段吗?始终仔细检查拼写和字符大小写。除非与 BindingFlags.IgnoreCase 一起使用,否则像 GetField、GetProperty... 这样的反射方法是区分大小写的。
  • 是否可以使用您提供的 BindingFlags 的值访问它(例如,它是静态的吗?)?

在您的情况下,如果您查看 GetField 的MSDN 文档,它会明确指出:

以下 BindingFlags 过滤器标志可用于定义要包含在搜索中的字段:

您必须指定 BindingFlags.Instance 或 BindingFlags.Static 才能获得 return

指定 BindingFlags.Public 以在搜索中包含公共字段。

指定 BindingFlags.NonPublic 以在搜索中包含非公共字段(即私有、内部和受保护的字段)。

指定 BindingFlags.FlattenHierarchy 以在层次结构中包含公共和受保护的静态成员;不包括继承类中的私有静态成员。

所以你应该使用 BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance而不是BindingFlags.Public | BindingFlags.NonPublic

也换

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

gen.Emit(OpCodes.Ldfld, field1);

并在您分配 field1 的行上使用正确的标志。

更新:您对 Main 的最后一次调用也有同样的问题。您需要在以下代码行中指定 BindingFlags.Static,因为您在代码的前面使用 MethodAttributes 将方法定义为静态:

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

此外,您不希望以您正在执行的方式检索属性访问器:您应该使用 GetProperty ,而不是使用带有访问器名称 (get_Text) 的 GetMethod :

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

希望有帮助。

于 2012-12-10T12:14:31.283 回答