使用Reflection.Emit创建动态程序集时自定义属性添加异常
解决Reflection.Emit中MethodImplAttribute不生效的问题
我之前也踩过这个坑,你遇到的问题大概率是构造函数获取错误,或者没正确完成特性的绑定步骤。咱们一步步来排查和修复:
常见问题原因
- 没拿到
MethodImplAttribute的正确构造函数重载 - 忘记调用
MethodBuilder.SetCustomAttribute来绑定特性 - 构造函数参数类型写错,导致获取到的构造函数为null
正确实现步骤
1. 正确获取构造函数
MethodImplAttribute最常用的是带MethodImplOptions参数的构造函数,一定要确保获取的是这个重载:
var methodImplCtor = typeof(System.Runtime.CompilerServices.MethodImplAttribute) .GetConstructor(new[] { typeof(System.Runtime.CompilerServices.MethodImplOptions) });
注意别写错命名空间,不然可能会获取到错误的类型或构造函数。
2. 创建特性构建器
用CustomAttributeBuilder来封装特性的构造参数,比如我们要设置MethodImplOptions.Synchronized:
var attributeBuilder = new CustomAttributeBuilder( methodImplCtor, new object[] { System.Runtime.CompilerServices.MethodImplOptions.Synchronized });
3. 绑定到目标方法
一定要调用MethodBuilder的SetCustomAttribute方法,把特性绑定到方法上:
methodBuilder.SetCustomAttribute(attributeBuilder);
完整可运行示例
给你一个完整的代码示例,包含创建程序集、添加特性、保存和验证的全流程:
using System; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; class DynamicAssemblyDemo { static void Main() { // 1. 创建动态程序集和模块 var assemblyName = new AssemblyName("DynamicTestAssembly"); var assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly( assemblyName, AssemblyBuilderAccess.RunAndSave); var moduleBuilder = assemblyBuilder.DefineDynamicModule(assemblyName.Name, "DynamicTestAssembly.dll"); // 2. 创建类型和方法 var typeBuilder = moduleBuilder.DefineType("TestType", TypeAttributes.Public); var methodBuilder = typeBuilder.DefineMethod( "TestMethod", MethodAttributes.Public | MethodAttributes.Static, typeof(void), Type.EmptyTypes); // 3. 配置MethodImplAttribute var ctor = typeof(MethodImplAttribute).GetConstructor(new[] { typeof(MethodImplOptions) }); if (ctor == null) { throw new InvalidOperationException("无法找到MethodImplAttribute的目标构造函数"); } var attrBuilder = new CustomAttributeBuilder(ctor, new object[] { MethodImplOptions.NoInlining }); methodBuilder.SetCustomAttribute(attrBuilder); // 4. 实现方法体(简单返回) var il = methodBuilder.GetILGenerator(); il.Emit(OpCodes.Ret); // 5. 完成类型创建并保存程序集 typeBuilder.CreateType(); assemblyBuilder.Save("DynamicTestAssembly.dll"); // 6. 加载验证特性 var loadedAssembly = Assembly.LoadFrom("DynamicTestAssembly.dll"); var loadedType = loadedAssembly.GetType("TestType"); var loadedMethod = loadedType.GetMethod("TestMethod"); var attributes = loadedMethod.GetCustomAttributes(typeof(MethodImplAttribute), false); if (attributes.Length > 0) { var implAttr = (MethodImplAttribute)attributes[0]; Console.WriteLine($"成功获取到特性,配置选项:{implAttr.Value}"); } else { Console.WriteLine("未找到MethodImplAttribute"); } } }
额外注意点
如果你需要使用无参构造函数,再手动设置Value属性,那就要用CustomAttributeBuilder的另一个重载,指定要设置的字段:
// 获取无参构造函数 var ctor = typeof(MethodImplAttribute).GetConstructor(Type.EmptyTypes); // 获取Value字段 var valueField = typeof(MethodImplAttribute).GetField("Value"); // 创建特性构建器,同时设置字段值 var attrBuilder = new CustomAttributeBuilder( ctor, new object[0], new[] { valueField }, new object[] { MethodImplOptions.NoOptimization });
内容的提问来源于stack exchange,提问作者Mr Anderson
相关产品推荐
相关产品推荐

