在Reflection.Emit程序集

时间:2018-04-02 21:30:24

标签: c# reflection.emit

在使用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!

2 个答案:

答案 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);