c# - 如何: Define a Self Referenced Type Property with Reflection Emit in c#

标签 c# reflection collections typebuilder

如何定义自引用的集合属性? 我想使用 Reflection Type Builder 构建的类型。

public class Sample
{
    public Sample()
    {
       Items = new List<Sample>();
    }
    public List<Sample> Items { get; set; }
    Public void AddSample(Sample item)
    {
       items.Add(item);
    }
}

我写的代码

AppDomain myDomain = AppDomain.CurrentDomain;
AssemblyName myAsmName = new AssemblyName("GenericEmit");
AssemblyBuilder myAssembly = myDomain.DefineDynamicAssembly(myAsmName, AssemblyBuilderAccess.RunAndSave);

ModuleBuilder myModule = myAssembly.DefineDynamicModule(myAsmName.Name, myAsmName.Name + ".dll");
TypeBuilder myType = myModule.DefineType("Sample", TypeAttributes.Public);  
Type listOf = typeof(List<>);
Type selfContained = listOf.MakeGenericType(myType);
myType.DefineProperty("Items", PropertyAttributes.None, selfContained, null);                
Type type= myType.CreateType();
Activator.CreateInstance(type);
myAssembly.Save(myAsmName.Name + ".dll");

最佳答案

您必须通过发射字段手动定义“支持字段”,并为您的属性定义 getter 和 setter。

AppDomain myDomain = AppDomain.CurrentDomain;
AssemblyName myAsmName = new AssemblyName("GenericEmit");
AssemblyBuilder myAssembly = myDomain.DefineDynamicAssembly(myAsmName, AssemblyBuilderAccess.RunAndSave);

ModuleBuilder myModule = myAssembly.DefineDynamicModule(myAsmName.Name, myAsmName.Name + ".dll");
TypeBuilder myType = myModule.DefineType("Sample", TypeAttributes.Public);
Type listOf = typeof(List<>);
Type selfContained = listOf.MakeGenericType(myType);

//define a backingfield
FieldBuilder field = myType.DefineField("<Items>_BackingField", selfContained, FieldAttributes.Private);

//define a parameterless constructor to initialize the field.
ConstructorBuilder constructor = myType.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, Type.EmptyTypes);
ILGenerator constructorBody = constructor.GetILGenerator();
constructorBody.Emit(OpCodes.Ldarg_0);
constructorBody.Emit(OpCodes.Call, typeof(object).GetConstructor(Type.EmptyTypes));
constructorBody.Emit(OpCodes.Ldarg_0);
constructorBody.Emit(OpCodes.Newobj, TypeBuilder.GetConstructor(selfContained, listOf.GetConstructor(Type.EmptyTypes)));
constructorBody.Emit(OpCodes.Stfld, field);
constructorBody.Emit(OpCodes.Ret);

//define the getter
MethodBuilder getter = myType.DefineMethod("get_Items", MethodAttributes.Public | MethodAttributes.HideBySig, selfContained, Type.EmptyTypes);
ILGenerator getterBody = getter.GetILGenerator();
getterBody.Emit(OpCodes.Ldarg_0);
getterBody.Emit(OpCodes.Ldfld, field);
getterBody.Emit(OpCodes.Ret);

//define the setter
MethodBuilder setter = myType.DefineMethod("set_Items", MethodAttributes.Public | MethodAttributes.HideBySig, typeof(void), new Type[] { selfContained });
ILGenerator setterBody = setter.GetILGenerator();
setterBody.Emit(OpCodes.Ldarg_0);
setterBody.Emit(OpCodes.Ldarg_1);
setterBody.Emit(OpCodes.Stfld, field);
setterBody.Emit(OpCodes.Ret);

PropertyBuilder property = myType.DefineProperty("Items", PropertyAttributes.None, selfContained, null);

//Bind getter and setter
property.SetGetMethod(getter);
property.SetSetMethod(setter);

//AddSample method
var addSampleMethod = myType.DefineMethod("AddSample", MethodAttributes.Private, CallingConventions.HasThis, typeof(void), new Type[] { myType }};
var addSampleMethodBody = addSampleMethod.GetILGenerator();
addSampleMethodBody.Emit(OpCodes.Ldarg_0);
addSampleMethodBody.Emit(OpCodes.Ldfld, field);
addSampleMethodBody.Emit(OpCodes.Ldarg_1);
addSampleMethodBody.Emit(OpCodes.Callvirt, TypeBuilder.GetMethod(selfContained, typeof(List<>).GetMethod("Add"));
addSampleMethodBody.Emit(OpCodes.Ret);

Type type = myType.CreateType();
myAssembly.Save(myAsmName.Name + ".dll");

var sample = Activator.CreateInstance(type);

关于c# - 如何: Define a Self Referenced Type Property with Reflection Emit in c#,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41055488/

相关文章:

c# - jQuery 模板忽略 String.Empty 值

c# - 按分隔符匹配正则表达式模式

Java 注解反射排序

java - Hashmap 使用哪个键和值来搜索姓名和电话号码

c# - Visual Studio Intellisense 不显示某些类

c# - 将非托管 C++ DLL 动态和静态导入 C# 不起作用

.net - 解析程序集合格名称?

reflection - 如何获取实现接口(interface)的 Go 包中定义的所有类型?

REST 集合,良好的做法 : GET api/CollectionA/<collection id>/CollectionB?

c# - 我不认为我正在修改这个集合