• MSIL实用指南-生成属性


    本篇讲解怎么生成属性,包括get和set方法。


    第一步,生成一个字段
    生成字段用TypeBuilder.DefineField方法。
    实例代码:

    FieldBuilder customerNameBldr = typeBuilder.DefineField
    ("_CustomerName",typeof(string),FieldAttributes.Private);

    第二步,创建一个PropertyBuilder对象
    创建PropertyBuilder对象需要用生成字段用方法
    TypeBuilder.DefineProperty(string name, PropertyAttributes attributes, Type returnType, Type[] parameterTypes)。
    返回的是一个PropertyBuilder对象。
    参数说明:
    name: 属性的名称。name 不能包含嵌入的 null 值。
    attributes: 属性的特性。
    returnType: 属性的返回类型。
    parameterTypes:属性的参数类型。

    实例代码:

    PropertyBuilder custNamePropBldr = typeBuilder.DefineProperty
    ("CustomerName", PropertyAttributes.HasDefault,typeof(string),null);

    第三步,生成get和set方法
    get和set方法的特性需要是 MethodAttributes.SpecialName | MethodAttributes.HideBySig ,
    实例代码:

    MethodAttributes getSetAttr =
    MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig;

    get方法需要无参,返回类型与相关字段类型相同。
    set方法需要一个参数,并且参数类型与相关字段的类型相同,无返回值。
    实例代码:

    MethodBuilder custNameGetPropMthdBldr =
    typeBuilder.DefineMethod("get_CustomerName", getSetAttr,typeof(string),Type.EmptyTypes);
    MethodBuilder custNameSetPropMthdBldr =
    typeBuilder.DefineMethod("set_CustomerName",getSetAttr,null,new Type[] { typeof(string) });

    第四步:实现get和set的方法体
    这里直接给一个实例
    实例代码:

    ILGenerator custNameGetIL = custNameGetPropMthdBldr.GetILGenerator();
    custNameGetIL.Emit(OpCodes.Ldarg_0);
    custNameGetIL.Emit(OpCodes.Ldfld, customerNameBldr);
    custNameGetIL.Emit(OpCodes.Ret);
    
    ILGenerator custNameSetIL = custNameSetPropMthdBldr.GetILGenerator();
    custNameSetIL.Emit(OpCodes.Ldarg_0);
    custNameSetIL.Emit(OpCodes.Ldarg_1);
    custNameSetIL.Emit(OpCodes.Stfld, customerNameBldr);
    custNameSetIL.Emit(OpCodes.Ret);


    第五步,把get和set方法关联到PropertyBuilder对象上
    管理get和set方法分别用PropertyBuilder对象的SetGetMethod和SetSetMethod方法
    实例代码:

    custNamePropBldr.SetGetMethod(custNameGetPropMthdBldr);
    custNamePropBldr.SetSetMethod(custNameSetPropMthdBldr);

    如果要生成一个只能get的属性,那么只要生成一个get方法,只调用SetGetMethod设置。
    同理要生成一个只能set的属性,那么只要生成一个set方法,只调用SetSetMethod设置。


    完整程序如下:

    using System;
    using System.Reflection;
    using System.Reflection.Emit;
    
    namespace LX1_ILDemo
    {
        class Demo11_Property
        {
            static string binaryName = "Demo11_Property.dll";
            static string namespaceName = "LX1_ILDemo";
            static string typeName = "PropertyDemo";
    
            static AssemblyBuilder assemblyBuilder;
            static ModuleBuilder moduleBuilder;
            static TypeBuilder typeBuilder;
    
            private static void  Generate_Property1()
            {
                FieldBuilder customerNameBldr = typeBuilder.DefineField
                    ("_CustomerName",typeof(string),FieldAttributes.Private);
    
                PropertyBuilder custNamePropBldr = typeBuilder.DefineProperty
                    ("CustomerName", PropertyAttributes.HasDefault,typeof(string),null);
    
                MethodAttributes getSetAttr =
                    MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig;
    
                // 定义get方法
                MethodBuilder custNameGetPropMthdBldr =
                    typeBuilder.DefineMethod("get_CustomerName", getSetAttr,typeof(string),Type.EmptyTypes);
    
                ILGenerator custNameGetIL = custNameGetPropMthdBldr.GetILGenerator();
                custNameGetIL.Emit(OpCodes.Ldarg_0);
                custNameGetIL.Emit(OpCodes.Ldfld, customerNameBldr);
                custNameGetIL.Emit(OpCodes.Ret);
    
                // 定义set方法
                MethodBuilder custNameSetPropMthdBldr =
                    typeBuilder.DefineMethod("set_CustomerName",getSetAttr,null,new Type[] { typeof(string) });
    
                ILGenerator custNameSetIL = custNameSetPropMthdBldr.GetILGenerator();
                custNameSetIL.Emit(OpCodes.Ldarg_0);
                custNameSetIL.Emit(OpCodes.Ldarg_1);
                custNameSetIL.Emit(OpCodes.Stfld, customerNameBldr);
                custNameSetIL.Emit(OpCodes.Ret);
    
                custNamePropBldr.SetGetMethod(custNameGetPropMthdBldr);
                custNamePropBldr.SetSetMethod(custNameSetPropMthdBldr);
            }
    
            private static void Generate_Property2()
            {
                FieldBuilder orgNameBldr = typeBuilder.DefineField
                    ("_OrgName", typeof(string), FieldAttributes.Private);
    
                PropertyBuilder orgPropBldr = typeBuilder.DefineProperty
                    ("OrgName", PropertyAttributes.HasDefault, typeof(string), null);
    
                MethodAttributes getSetAttr =
                    MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig;
    
                MethodBuilder custNameGetPropMthdBldr =
                    typeBuilder.DefineMethod("get_OrgName", getSetAttr, typeof(string), Type.EmptyTypes);
    
                ILGenerator custNameGetIL = custNameGetPropMthdBldr.GetILGenerator();
    
                custNameGetIL.Emit(OpCodes.Ldarg_0);
                custNameGetIL.Emit(OpCodes.Ldfld, orgNameBldr);
                custNameGetIL.Emit(OpCodes.Ret);
                orgPropBldr.SetGetMethod(custNameGetPropMthdBldr);
            }
    
            public static void Generate()
            {
                InitAssembly();
    
                typeBuilder = moduleBuilder.DefineType( namespaceName+"."+ typeName, TypeAttributes.Public);
    
                Generate_Property1();
                Generate_Property2();
    
                SaveAssembly();
                Console.WriteLine("生成成功");
            }
    
            static void InitAssembly()
            {
                AssemblyName assemblyName = new AssemblyName(namespaceName);
                assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndSave);
                moduleBuilder = assemblyBuilder.DefineDynamicModule(assemblyName.Name, binaryName);
            }
    
            static void SaveAssembly()
            {
                Type t = typeBuilder.CreateType(); //完成Type,这是必须的
                assemblyBuilder.Save(binaryName);
            }
        }
    }
    View Code
  • 相关阅读:
    Unity 深入解析合批(Batching)原理及失败原因
    ILRuntime作者林若峰分享:优化 Dots URP 性能优化 (干货满满)
    unity Mesh绘制网格线
    Shder基础知识
    UnityEditor工具链开发的常用小技巧与示例
    磁盘文件分析清理工具
    波函数坍塌算法(Wave Collapse Function)实现随机地图
    视觉小说 文字游戏引擎 ink 可配合Unity
    c# 字典键值排序
    unity文件夹复制
  • 原文地址:https://www.cnblogs.com/tkt2016/p/8630142.html
Copyright © 2020-2023  润新知