在使用Relection.Emit
创建动态程序集时,我正在尝试创建一个方法并使用System.Runtime.CompilerServices.MethodImplAttribute
进行装饰。我使用该方法成功创建并保存程序集,但是当我加载已保存的程序集时,我的方法似乎没有任何自定义属性。这是我创建程序集的代码:
ConstructorInfo methodImplCtor = typeof(System.Runtime.CompilerServices.MethodImplAttribute).GetConstructor(new[] { typeof(System.Runtime.CompilerServices.MethodImplOptions) });
// stores the constructor I wish to use
AssemblyBuilder assm = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName("MyAssembly"), AssemblyBuilderAccess.Save);
ModuleBuilder module = assm.DefineDynamicModule("MyAssembly", "MyAssembly.dll", false);
TypeBuilder type = module.DefineType("MyAssembly.MyType", TypeAttributes.Public | TypeAttributes.Abstract | TypeAttributes.Sealed);
MethodBuilder method = type.DefineMethod("MyMethod", MethodAttributes.Public | MethodAttributes.Static | MethodAttributes.HideBySig, typeof(int), new[] { typeof(int) });
method.SetCustomAttribute(new CustomAttributeBuilder(methodImplCtor, new object[] { System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining }));
ILGenerator il = method.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ret);
type.CreateType();
assm.Save("MyAssembly.dll");
在上面的代码运行之后,我抓住MyAssembly.dll文件并在另一个项目中引用它。当我运行此代码时,它报告我的方法上没有自定义属性:
var attributes = typeof(MyAssembly.MyType).GetMethod("MyMethod").GetCustomAttributes(false);
// empty array!
答案 0 :(得分:1)
那是因为某些属性不是真正的属性,而实际上是IL原语。这适用于[Serializable]
和其他一些 - 包括(显然)这一个;这是来自“ildasm”的IL:
.method public hidebysig static int32 MyMethod(int32 A_0) cil managed aggressiveinlining
{
// Code size 2 (0x2)
.maxstack 1
IL_0000: ldarg.0
IL_0001: ret
} // end of method MyType::MyMethod
请注意aggressiveinlining
。
答案 1 :(得分:1)
这是特殊属性,如documentation中所述:
MethodImplOptions枚举的成员对应于bit CorMethodImpl元数据表中的字段。这意味着 无法在运行时通过检索有关该属性的信息 调用MemberInfo.GetCustomAttributes方法;相反,它是 通过调用来检索 MethodInfo.GetMethodImplementationFlags或者 ConstructorInfo.GetMethodImplementationFlags方法。
因此它已正确应用,您可以通过检查上面的文档说明来验证:
bool isAggressiveInlined = typeof(MyAssembly.MyType).GetMethod("MyMethod")
.MethodImplementationFlags.HasFlag(MethodImplAttributes.AggressiveInlining);