这是我要实现的目标:在运行时,我想创建一个动态类,该动态类将覆盖任何T类。该想法是:生成的类将容纳3个类型为T的对象(我称之为原始对象) ,我将其称为“已修改”,其他我称为“活动”,并在这两者之间进行切换。
现在,我生成的类shoudl也扩展了T,而它的任何虚拟属性都将被覆盖(getter和setter),并将重定向到它拥有的Active对象的相同属性。
我的困难是:如何访问活动对象的属性?这是我的代码:
public static Type CompileResultType<T>()
{
//Gets Type builder that extends type T
TypeBuilder tb = GetTypeBuilder<T>($"{typeof(T).Name}Proxy");
ConstructorBuilder constructor = tb.DefineDefaultConstructor(MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName);
//Add Active field
FieldBuilder activeFieldBuilder = tb.DefineField("Active", typeof(T), FieldAttributes.Public);
//Add Original field
FieldBuilder originalFieldBuilder = tb.DefineField("Original", typeof(T), FieldAttributes.Public);
//Add Modified field
FieldBuilder FieldBuilder = tb.DefineField("Modified", typeof(T), FieldAttributes.Public);
//Get all public properties of type T
var allProperties = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);
//Get all virtual properties
var filteredProperties = allProperties.Where(p => p.GetGetMethod().IsVirtual && p.GetSetMethod().IsVirtual);
foreach (var property in filteredProperties)
CreateProperty<T>(tb, property.Name, property.PropertyType, property);
Type objectType = tb.CreateType();
var teste = tb.GetFields();
return objectType;
}
private static TypeBuilder GetTypeBuilder<T>(string typeSignature)
{
var an = new AssemblyName(typeSignature);
AssemblyBuilder assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(an, AssemblyBuilderAccess.Run);
ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("Mask.Builder");
TypeBuilder tb = moduleBuilder.DefineType(typeSignature, TypeAttributes.Public |
TypeAttributes.Class |
TypeAttributes.AutoClass |
TypeAttributes.AnsiClass |
TypeAttributes.BeforeFieldInit |
TypeAttributes.AutoLayout, typeof(T));
return tb;
}
private static void CreateProperty<T>(TypeBuilder tb, string propertyName, Type propertyType, PropertyInfo activeProperty)
{
//THE PROBLEM LIES HERE: Trying to access the respective property of object Active, but doesn't work
FieldBuilder fieldBuilder = tb.DefineField("Active." + propertyName, propertyType, FieldAttributes.Private);
PropertyBuilder propertyBuilder = tb.DefineProperty(propertyName, PropertyAttributes.HasDefault, propertyType, null);
//Create Getter that will retrieve "Active.PROPERTY"
MethodBuilder getPropMthdBldr = tb.DefineMethod("get_" + propertyName, MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig | MethodAttributes.Virtual, propertyType, Type.EmptyTypes);
ILGenerator getIl = getPropMthdBldr.GetILGenerator();
getIl.Emit(OpCodes.Ldarg_0);
getIl.Emit(OpCodes.Ldfld, fieldBuilder);
getIl.Emit(OpCodes.Ret);
//Create Setter that will write into "Active.PROPERTY"
MethodBuilder setPropMthdBldr = tb.DefineMethod("set_" + propertyName, MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig | MethodAttributes.Virtual, null, new[] { propertyType });
ILGenerator setIl = setPropMthdBldr.GetILGenerator();
Label modifyProperty = setIl.DefineLabel();
Label exitSet = setIl.DefineLabel();
setIl.MarkLabel(modifyProperty);
setIl.Emit(OpCodes.Ldarg_0);
setIl.Emit(OpCodes.Ldarg_1);
setIl.Emit(OpCodes.Stfld, fieldBuilder);
setIl.Emit(OpCodes.Nop);
setIl.MarkLabel(exitSet);
setIl.Emit(OpCodes.Ret);
propertyBuilder.SetGetMethod(getPropMthdBldr);
propertyBuilder.SetSetMethod(setPropMthdBldr);
}