.NET Core 2.0下Reflection.Emit调用DoClass方法的CLR无效程序错误求助
嘿,我之前在使用Reflection.Emit动态生成类型时也踩过类似的CLR无效程序错误的坑,尤其是在添加自定义注释属性的时候。结合你的场景,我帮你梳理下可能的问题点和解决办法:
问题根源分析
出现"Common Language Runtime detected an invalid program"错误,本质是你生成的IL代码或元数据不符合CLR的验证规范。添加"ToDo"注释后触发问题,说明属性的生成逻辑破坏了类型/方法的元数据一致性,常见原因有这几个:
- 属性构造参数传递错误:如果你的
ToDoAttribute需要特定参数(比如字符串),Emit时没有正确加载参数值,导致元数据结构异常 - 手动Emit属性元数据时出错:直接用
ILGenerator写属性的元数据很容易写错指令序列,不如官方提供的工具类可靠 - 方法IL与属性元数据衔接错误:添加属性时干扰了方法体的IL指令流,导致方法的执行逻辑不符合CLR要求
排查与解决步骤
1. 先做最小化验证
先去掉"ToDo"注释的代码,确认DoClass方法能正常调用。如果没问题,100%可以确定问题出在属性添加的环节。
2. 确保ToDoAttribute的定义合法
首先检查你的注释属性是否是标准的Attribute类:
// 正确的自定义Attribute示例 public class ToDoAttribute : Attribute { // 确保构造函数参数类型明确 public ToDoAttribute(string note) { Note = note; } public string Note { get; } }
3. 用CustomAttributeBuilder替代手动Emit属性
不要自己写IL来生成属性元数据,.NET提供了CustomAttributeBuilder来安全地生成自定义属性,这是最不容易出错的方式:
// 假设你已经有了TypeBuilder和MethodBuilder的实例 var methodBuilder = typeBuilder.DefineMethod( "DoClass", MethodAttributes.Public | MethodAttributes.Virtual, typeof(void), Type.EmptyTypes); // 先编写方法体的IL(比如简单的返回) var il = methodBuilder.GetILGenerator(); il.Emit(OpCodes.Ret); // 用CustomAttributeBuilder添加ToDo注释 var todoAttrType = typeof(ToDoAttribute); // 找到属性的构造函数(参数类型要完全匹配) var ctor = todoAttrType.GetConstructor(new[] { typeof(string) }); var attrBuilder = new CustomAttributeBuilder(ctor, new object[] { "ToDo" }); // 给方法添加属性 methodBuilder.SetCustomAttribute(attrBuilder); // 后续创建类型并调用 var dynamicType = typeBuilder.CreateType(); var instance = Activator.CreateInstance(dynamicType); dynamicType.GetMethod("DoClass").Invoke(instance, null);
4. 验证生成的元数据
如果还是有问题,可以用ILSpy或dnSpy反编译你生成的动态程序集,检查:
DoClass方法的IL指令是否完整(比如有没有遗漏Ret指令)ToDo属性的元数据是否正确(参数值是否存在,类型是否匹配)
5. 注意.NET Core 2.0的特殊性
.NET Core 2.0对Reflection.Emit的元数据验证比.NET Framework更严格,比如:
- 属性构造函数的参数不能有隐式类型转换
- 动态模块的访问权限要设置正确(用
AssemblyBuilderAccess.Run即可)
内容的提问来源于stack exchange,提问作者popelenkow
相关产品推荐
相关产品推荐

