如何:在C#中使用反射发射定义自引用类型属性 [英] How to: Define a Self Referenced Type Property with Reflection Emit in c#

查看:194
本文介绍了如何:在C#中使用反射发射定义自引用类型属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何定义自引用集合属性?
我要使用反射类型生成器构建的类型。

How to define self referenced collection property ? Type I want to build with 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");


推荐答案

您必须通过以下方式手动定义后备字段

You have to define manually the "backing field" by emitting field and define getter and setter for your property.

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#中使用反射发射定义自引用类型属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆