Reflection.Emit 程序集中未正确添加自定义属性
Custom Attribute not added correctly in Reflection.Emit assembly
在使用 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");
在上面的代码 运行s 之后,我抓取 MyAssembly.dll 文件并在不同的项目中引用它。当我 运行 这段代码时,它报告我的方法中有零个自定义属性:
var attributes = typeof(MyAssembly.MyType).GetMethod("MyMethod").GetCustomAttributes(false);
// empty array!
那是因为某些属性 并不是真正的属性 ,而实际上是 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
。
这是特殊属性,如其documentation所述:
The members of the MethodImplOptions enumeration correspond to bit
fields in the CorMethodImpl metadata table. This means that
information on the attribute cannot be retrieved at run time by
calling the MemberInfo.GetCustomAttributes method; instead, it is
retrieved by calling either the
MethodInfo.GetMethodImplementationFlags or the
ConstructorInfo.GetMethodImplementationFlags method.
所以它应用正确,您可以通过检查上面的文档来验证:
bool isAggressiveInlined = typeof(MyAssembly.MyType).GetMethod("MyMethod")
.MethodImplementationFlags.HasFlag(MethodImplAttributes.AggressiveInlining);
在使用 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");
在上面的代码 运行s 之后,我抓取 MyAssembly.dll 文件并在不同的项目中引用它。当我 运行 这段代码时,它报告我的方法中有零个自定义属性:
var attributes = typeof(MyAssembly.MyType).GetMethod("MyMethod").GetCustomAttributes(false);
// empty array!
那是因为某些属性 并不是真正的属性 ,而实际上是 IL 原语。这适用于 [Serializable]
,以及其他一些 - 包括(显然)这个;这是来自 "ildasm":
.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
。
这是特殊属性,如其documentation所述:
The members of the MethodImplOptions enumeration correspond to bit fields in the CorMethodImpl metadata table. This means that information on the attribute cannot be retrieved at run time by calling the MemberInfo.GetCustomAttributes method; instead, it is retrieved by calling either the MethodInfo.GetMethodImplementationFlags or the ConstructorInfo.GetMethodImplementationFlags method.
所以它应用正确,您可以通过检查上面的文档来验证:
bool isAggressiveInlined = typeof(MyAssembly.MyType).GetMethod("MyMethod")
.MethodImplementationFlags.HasFlag(MethodImplAttributes.AggressiveInlining);