我正在尝试撰写extension
method
,其中new
type
将返回名为type
+
个旧属性的所有属性ClosedDt。我现在得到了这个:
public static object GetDynamicObject(this System.Reflection.Emit.TypeBuilder typeBuilder,AssemblyName assembly, Type objectType)
{
AppDomain appDomain = System.Threading.Thread.GetDomain();
AssemblyBuilder assemblyBuilder = appDomain.DefineDynamicAssembly(assembly, AssemblyBuilderAccess.Run);
ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule(assembly.Name);
//create the class
typeBuilder = moduleBuilder.DefineType(objectType.Name, TypeAttributes.Public | TypeAttributes.AutoClass | TypeAttributes.AnsiClass |
TypeAttributes.BeforeFieldInit, typeof(System.Object));
foreach (var prop in objectType.GetProperties())
{
FieldBuilder fieldBuilder = typeBuilder.DefineField(prop.Name.Substring(0, 1).ToLower() + prop.Name.Substring(1),
prop.PropertyType, FieldAttributes.Private);
PropertyBuilder propertyBuilder = typeBuilder.DefineProperty(prop.Name, PropertyAttributes.None,
prop.PropertyType, new Type[]{prop.PropertyType});
MethodBuilder propertyGetter = typeBuilder.DefineMethod("get_" + prop.Name, MethodAttributes.Public | MethodAttributes.HideBySig, prop.PropertyType, new Type[] { prop.PropertyType });
var ilGenerator = propertyGetter.GetILGenerator();
ilGenerator.Emit(OpCodes.Ldarg_0);
ilGenerator.Emit(OpCodes.Ldfld,fieldBuilder);
ilGenerator.Emit(OpCodes.Ret);
MethodBuilder propertySetter = typeBuilder.DefineMethod("set_"+prop.Name, MethodAttributes.Public | MethodAttributes.HideBySig, prop.PropertyType, new Type[] { prop.PropertyType });
var propertySetterIl = propertySetter.GetILGenerator();
propertySetterIl.Emit(OpCodes.Ldarg_0);
propertySetterIl.Emit(OpCodes.Ldarg_1);
propertySetterIl.Emit(OpCodes.Stfld, fieldBuilder);
propertySetterIl.Emit(OpCodes.Ret);
propertyBuilder.SetGetMethod(propertyGetter);
propertyBuilder.SetGetMethod(propertySetter);
}
FieldBuilder closedFieldBuilder = typeBuilder.DefineField("closedDt",
typeof(string), FieldAttributes.Private);
PropertyBuilder closedPropertyBuilder = typeBuilder.DefineProperty("ClosedDt", PropertyAttributes.HasDefault,
typeof(string), null);
MethodBuilder closedPropertyGetter = typeBuilder.DefineMethod("get_ClosedDt", MethodAttributes.Public | MethodAttributes.SpecialName |
MethodAttributes.HideBySig, typeof(string), Type.EmptyTypes);
var ilGeneratorClosed = closedPropertyGetter.GetILGenerator();
ilGeneratorClosed.Emit(OpCodes.Ldarg_0);
ilGeneratorClosed.Emit(OpCodes.Ldfld, closedFieldBuilder);
ilGeneratorClosed.Emit(OpCodes.Ret);
MethodBuilder closedPropertySetter = typeBuilder.DefineMethod("set_ClosedDt", MethodAttributes.Public | MethodAttributes.SpecialName |
MethodAttributes.HideBySig, null, new Type[] { typeof(string) });
var closedPropertySetterIl = closedPropertySetter.GetILGenerator();
closedPropertySetterIl.Emit(OpCodes.Ldarg_0);
closedPropertySetterIl.Emit(OpCodes.Ldarg_1);
closedPropertySetterIl.Emit(OpCodes.Stfld, closedFieldBuilder);
closedPropertySetterIl.Emit(OpCodes.Ret);
closedPropertyBuilder.SetGetMethod(closedPropertyGetter);
closedPropertyBuilder.SetGetMethod(closedPropertySetter);
var dynamicType = typeBuilder.CreateType();
return Activator.CreateInstance(dynamicType);
}
对于记录:我知道如果我想在属性中添加一些属性,我需要从头开始创建新类。
但上面的代码只为private
fields
生成new
type
。
我错过了什么或我弄错了什么?
答案 0 :(得分:1)
我猜你在DefineMethod调用getter和setter时缺少MethodAttributes.SpecialName。这个代码分叉,并正确创建getter。
private static MethodBuilder BuildGetter(TypeBuilder typeBuilder, FieldInfo fieldBuilder, System.Reflection.Emit.PropertyBuilder propertyBuilder)
{
const MethodAttributes attributes =
MethodAttributes.Public |
MethodAttributes.HideBySig |
MethodAttributes.SpecialName |
MethodAttributes.Virtual |
MethodAttributes.Final;
var getterBuilder = typeBuilder.DefineMethod("get_" + propertyBuilder.Name, attributes, propertyBuilder.PropertyType, Type.EmptyTypes);
// Code generation
var ilgen = getterBuilder.GetILGenerator();
ilgen.Emit(OpCodes.Ldarg_0);
ilgen.Emit(OpCodes.Ldfld, fieldBuilder); // returning the firstname field
ilgen.Emit(OpCodes.Ret);
return getterBuilder;
}