以编程方式为现有 class 属性 添加新属性 Reflection.Emit
Programmatically Adding new attribute for existing class property with Reflection.Emit
我正在尝试以编程方式在 class 成员之上添加新属性 ...
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Text;
using System.Threading.Tasks;
namespace Test11
{
public class SomeAttribute : Attribute
{
public SomeAttribute(string value)
{
this.Value = value;
}
public string Value { get; set; }
}
// for attribute to be injected the property should be "virtual"
public class ClassA
{
public virtual int Value { get; set; }
}
public class Test
{
public static void Func()
{
var type = typeof(ClassA);
var aName = new System.Reflection.AssemblyName(Assembly.GetExecutingAssembly().GetName().Name);
var ab = AppDomain.CurrentDomain.DefineDynamicAssembly(aName, AssemblyBuilderAccess.Run);
var mb = ab.DefineDynamicModule(aName.Name);
var tb = mb.DefineType(type.Name + "Proxy", System.Reflection.TypeAttributes.Public, type);
var attrCtorParams = new Type[] { typeof(string) };
var attrCtorInfo = typeof(SomeAttribute).GetConstructor(attrCtorParams);
var attrBuilder = new CustomAttributeBuilder(attrCtorInfo, new object[] { "Some Value" });
tb.SetCustomAttribute(attrBuilder);
PropertyInfo info = typeof(ClassA).GetProperty("Value", BindingFlags.Public | BindingFlags.Instance);
PropertyBuilder newProp = tb.DefineProperty(info.Name, PropertyAttributes.None, info.PropertyType, Type.EmptyTypes);
newProp.SetCustomAttribute(attrBuilder);
//var tbValue = mb.DefineType(info.Name, System.Reflection.TypeAttributes.Public, type);
FieldBuilder ValueField = tb.DefineField("_Value", typeof(string), FieldAttributes.Private);
MethodAttributes GetSetAttributes = MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig | MethodAttributes.Virtual;
MethodBuilder ValuePropertyGet = tb.DefineMethod("get_Value", GetSetAttributes, typeof(string), Type.EmptyTypes);
ILGenerator Generator = ValuePropertyGet.GetILGenerator();
Generator.Emit(OpCodes.Ldarg_0);
Generator.Emit(OpCodes.Ldfld, ValueField);
Generator.Emit(OpCodes.Ret);
MethodBuilder ValuePropertySet = tb.DefineMethod("set_Value", GetSetAttributes, null, new Type[] { typeof(string) });
Generator = ValuePropertySet.GetILGenerator();
Generator.Emit(OpCodes.Ldarg_0);
Generator.Emit(OpCodes.Ldarg_1);
Generator.Emit(OpCodes.Stfld, ValueField);
Generator.Emit(OpCodes.Ret);
newProp.SetSetMethod(ValuePropertySet);
newProp.SetGetMethod(ValuePropertyGet);
var newType = tb.CreateType();
var instance = (ClassA)Activator.CreateInstance(newType);
var attr = (SomeAttribute)instance.GetType().GetCustomAttributes(typeof(SomeAttribute), false).SingleOrDefault();
var attr1 = (SomeAttribute)instance.Value.GetType().GetCustomAttributes(typeof(SomeAttribute), false).SingleOrDefault();
}
}
}
此代码为原始 class 创建了一个代理 class。
它可以轻松地为整个 class.
分配属性
对于 class 属性,我可以用新的 getter 和 setter 替换 属性,分配新的属性,但是我要求 属性 GetCustomAttribute returns 始终为 NULL
这一行:
var attr1 = (SomeAttribute)instance.Value.GetType().GetCustomAttributes(typeof(SomeAttribute), false).SingleOrDefault();
正在寻找 Value 类型(一个 int)的 SomeAttribute 属性,而不是新的 属性。
本质上,你在做
typeof(int).GetCustomAttributes(typeof(SomeAttribute), false).SingleOrDefault();
由于显而易见的原因,这将 return 为空。
应该是:
var attr1 = (SomeAttribute)instance.GetType().GetProperty(nameof(instance.Value), BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly).GetCustomAttributes(typeof(SomeAttribute), false).SingleOrDefault();
我正在尝试以编程方式在 class 成员之上添加新属性 ...
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Text;
using System.Threading.Tasks;
namespace Test11
{
public class SomeAttribute : Attribute
{
public SomeAttribute(string value)
{
this.Value = value;
}
public string Value { get; set; }
}
// for attribute to be injected the property should be "virtual"
public class ClassA
{
public virtual int Value { get; set; }
}
public class Test
{
public static void Func()
{
var type = typeof(ClassA);
var aName = new System.Reflection.AssemblyName(Assembly.GetExecutingAssembly().GetName().Name);
var ab = AppDomain.CurrentDomain.DefineDynamicAssembly(aName, AssemblyBuilderAccess.Run);
var mb = ab.DefineDynamicModule(aName.Name);
var tb = mb.DefineType(type.Name + "Proxy", System.Reflection.TypeAttributes.Public, type);
var attrCtorParams = new Type[] { typeof(string) };
var attrCtorInfo = typeof(SomeAttribute).GetConstructor(attrCtorParams);
var attrBuilder = new CustomAttributeBuilder(attrCtorInfo, new object[] { "Some Value" });
tb.SetCustomAttribute(attrBuilder);
PropertyInfo info = typeof(ClassA).GetProperty("Value", BindingFlags.Public | BindingFlags.Instance);
PropertyBuilder newProp = tb.DefineProperty(info.Name, PropertyAttributes.None, info.PropertyType, Type.EmptyTypes);
newProp.SetCustomAttribute(attrBuilder);
//var tbValue = mb.DefineType(info.Name, System.Reflection.TypeAttributes.Public, type);
FieldBuilder ValueField = tb.DefineField("_Value", typeof(string), FieldAttributes.Private);
MethodAttributes GetSetAttributes = MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig | MethodAttributes.Virtual;
MethodBuilder ValuePropertyGet = tb.DefineMethod("get_Value", GetSetAttributes, typeof(string), Type.EmptyTypes);
ILGenerator Generator = ValuePropertyGet.GetILGenerator();
Generator.Emit(OpCodes.Ldarg_0);
Generator.Emit(OpCodes.Ldfld, ValueField);
Generator.Emit(OpCodes.Ret);
MethodBuilder ValuePropertySet = tb.DefineMethod("set_Value", GetSetAttributes, null, new Type[] { typeof(string) });
Generator = ValuePropertySet.GetILGenerator();
Generator.Emit(OpCodes.Ldarg_0);
Generator.Emit(OpCodes.Ldarg_1);
Generator.Emit(OpCodes.Stfld, ValueField);
Generator.Emit(OpCodes.Ret);
newProp.SetSetMethod(ValuePropertySet);
newProp.SetGetMethod(ValuePropertyGet);
var newType = tb.CreateType();
var instance = (ClassA)Activator.CreateInstance(newType);
var attr = (SomeAttribute)instance.GetType().GetCustomAttributes(typeof(SomeAttribute), false).SingleOrDefault();
var attr1 = (SomeAttribute)instance.Value.GetType().GetCustomAttributes(typeof(SomeAttribute), false).SingleOrDefault();
}
}
}
此代码为原始 class 创建了一个代理 class。 它可以轻松地为整个 class.
分配属性对于 class 属性,我可以用新的 getter 和 setter 替换 属性,分配新的属性,但是我要求 属性 GetCustomAttribute returns 始终为 NULL
这一行:
var attr1 = (SomeAttribute)instance.Value.GetType().GetCustomAttributes(typeof(SomeAttribute), false).SingleOrDefault();
正在寻找 Value 类型(一个 int)的 SomeAttribute 属性,而不是新的 属性。
本质上,你在做
typeof(int).GetCustomAttributes(typeof(SomeAttribute), false).SingleOrDefault();
由于显而易见的原因,这将 return 为空。
应该是:
var attr1 = (SomeAttribute)instance.GetType().GetProperty(nameof(instance.Value), BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly).GetCustomAttributes(typeof(SomeAttribute), false).SingleOrDefault();