• MSIL实用指南-生成索引器


    MSIL实用指南-生成索引器

    索引器是一种特殊的属性,它有参数的,也有get和set方法,属性名称一般是"Item",并且方法名称一般名称是"get_Item"和"set_Item"。

    下面我们来生成如下的带有索引器的类

    using System;
    
    namespace LX1_ILDemo
    {
        public class IndexerDemo
        {
            private string[,] _CustomerNames;
    
            public string this[int, int]
            {
                get
                {
                    return this._CustomerNames[num, num2];
                }
                set
                {
                    this._CustomerNames[num, num2] = value;
                }
            }
        }
    }
    View Code

    第一步,生成一个字段
    生成字段用TypeBuilder.DefineField方法。
    实例代码:
    FieldBuilder CustomerNamesBldr = typeBuilder.DefineField
    ("_CustomerNames",typeof(string[,]),FieldAttributes.Private);

    第二步,创建一个名称为Item的PropertyBuilder对象
    创建PropertyBuilder对象需要用生成字段用方法

    PropertyBuilder custNamePropBldr = typeBuilder.DefineProperty
    ("Item", PropertyAttributes.HasDefault,typeof(string),new Type[] { typeof(int), typeof(int) });

    注意定义这个PropertyBuilder对象是有参数new Type[] { typeof(int), typeof(int) }的。


    第三步,生成get和set方法
    方法名为"get_Item"和"set_Item"。

    MethodAttributes getSetAttr =
    MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig;
    
    // 定义get方法
    MethodBuilder custNameGetPropMthdBldr =
    typeBuilder.DefineMethod("get_Item", getSetAttr, typeof(string) , new Type[] { typeof(int), typeof(int) });
    
    ILGenerator ilGetGenerator = custNameGetPropMthdBldr.GetILGenerator();
    LocalBuilder localBuilderv1 = ilGetGenerator.DeclareLocal(typeof(string));
    ilGetGenerator.Emit(OpCodes.Ldarg_0);
    ilGetGenerator.Emit(OpCodes.Ldfld, CustomerNamesBldr);
    ilGetGenerator.Emit(OpCodes.Ldarg_1);
    ilGetGenerator.Emit(OpCodes.Ldarg_2);
    ilGetGenerator.Emit(OpCodes.Call ,typeof(string[,]).GetMethod("Get",new Type[] { typeof(int), typeof(int) }));
    ilGetGenerator.Emit(OpCodes.Stloc_0);
    ilGetGenerator.Emit(OpCodes.Ldloc_0);
    ilGetGenerator.Emit(OpCodes.Ret);
    
    // 定义set方法
    MethodBuilder custNameSetPropMthdBldr =
    typeBuilder.DefineMethod("set_Item", getSetAttr, null, new Type[] { typeof(int), typeof(int), typeof(string) });
    
    ILGenerator ilSetGenerator = custNameSetPropMthdBldr.GetILGenerator();
    ilSetGenerator.Emit(OpCodes.Ldarg_0);
    ilSetGenerator.Emit(OpCodes.Ldfld, CustomerNamesBldr);
    ilSetGenerator.Emit(OpCodes.Ldarg_1);
    ilSetGenerator.Emit(OpCodes.Ldarg_2);
    ilSetGenerator.Emit(OpCodes.Ldarg_3);
    ilSetGenerator.Emit(OpCodes.Call, typeof(string[,]).GetMethod("Set", new Type[] { typeof(int), typeof(int), typeof(string) }));
    ilSetGenerator.Emit(OpCodes.Ret);
    
    custNamePropBldr.SetGetMethod(custNameGetPropMthdBldr);
    custNamePropBldr.SetSetMethod(custNameSetPropMthdBldr);

    第四步,给类加DefaultMemberAttribute特性
    用反射查找DefaultMemberAttribute类型,传入参数值为"Item",创建一个DefaultMemberAttribute实例,
    源码如下

    Type myType = typeof(DefaultMemberAttribute);
    ConstructorInfo infoConstructor = myType.GetConstructor(new Type[] { typeof(string) });
    CustomAttributeBuilder attributeBuilder = new CustomAttributeBuilder(infoConstructor, new object[] {"Item" });
    typeBuilder.SetCustomAttribute(attributeBuilder);

    完整程序如下:

    using System;
    using System.Reflection;
    using System.Reflection.Emit;
    
    namespace LX1_ILDemo
    {
        class Demo12_Indexer
        {
            static string binaryName = "Demo12_Indexer.dll";
            static string namespaceName = "LX1_ILDemo";
            static string typeName = "IndexerDemo";
    
            static AssemblyBuilder assemblyBuilder;
            static ModuleBuilder moduleBuilder;
            static TypeBuilder typeBuilder;
    
            private static void  Generate_Indexer()
            {
                FieldBuilder CustomerNamesBldr = typeBuilder.DefineField
                    ("_CustomerNames",typeof(string[,]),FieldAttributes.Private);
    
                PropertyBuilder custNamePropBldr = typeBuilder.DefineProperty
                    ("Item", PropertyAttributes.HasDefault,typeof(string),new Type[] { typeof(int), typeof(int) });
    
                MethodAttributes getSetAttr =
                    MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig;
    
                // 定义get方法
                MethodBuilder custNameGetPropMthdBldr =
                    typeBuilder.DefineMethod("get_Item", getSetAttr, typeof(string) , new Type[] { typeof(int), typeof(int) });
    
                ILGenerator ilGetGenerator = custNameGetPropMthdBldr.GetILGenerator();
                LocalBuilder localBuilderv1 = ilGetGenerator.DeclareLocal(typeof(string));
                ilGetGenerator.Emit(OpCodes.Ldarg_0);
                ilGetGenerator.Emit(OpCodes.Ldfld, CustomerNamesBldr);
                ilGetGenerator.Emit(OpCodes.Ldarg_1);
                ilGetGenerator.Emit(OpCodes.Ldarg_2);
                ilGetGenerator.Emit(OpCodes.Call ,typeof(string[,]).GetMethod("Get",new Type[] { typeof(int), typeof(int) }));
                ilGetGenerator.Emit(OpCodes.Stloc_0);
                ilGetGenerator.Emit(OpCodes.Ldloc_0);
                ilGetGenerator.Emit(OpCodes.Ret);
    
                // 定义set方法
                MethodBuilder custNameSetPropMthdBldr =
                    typeBuilder.DefineMethod("set_Item", getSetAttr, null, new Type[] { typeof(int), typeof(int), typeof(string) });
    
                ILGenerator ilSetGenerator = custNameSetPropMthdBldr.GetILGenerator();
                ilSetGenerator.Emit(OpCodes.Ldarg_0);
                ilSetGenerator.Emit(OpCodes.Ldfld, CustomerNamesBldr);
                ilSetGenerator.Emit(OpCodes.Ldarg_1);
                ilSetGenerator.Emit(OpCodes.Ldarg_2);
                ilSetGenerator.Emit(OpCodes.Ldarg_3);
                ilSetGenerator.Emit(OpCodes.Call, typeof(string[,]).GetMethod("Set", new Type[] { typeof(int), typeof(int), typeof(string) }));
                ilSetGenerator.Emit(OpCodes.Ret);
    
                custNamePropBldr.SetGetMethod(custNameGetPropMthdBldr);
                custNamePropBldr.SetSetMethod(custNameSetPropMthdBldr);
    
                SetTypeAttr();
            }
    
            private static void SetTypeAttr()
            {
                Type myType =  typeof(DefaultMemberAttribute);
                ConstructorInfo infoConstructor = myType.GetConstructor(new Type[] { typeof(string) });
                CustomAttributeBuilder attributeBuilder = new CustomAttributeBuilder(infoConstructor, new object[] {"Item" });
                typeBuilder.SetCustomAttribute(attributeBuilder);
            }
    
            public static void Generate()
            {
                InitAssembly();
    
                typeBuilder = moduleBuilder.DefineType( namespaceName+"."+ typeName, TypeAttributes.Public);
                Generate_Indexer();
    
                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
  • 相关阅读:
    Redis 客户端
    Redis 数据库
    Redis 对象
    Redis 跳跃表
    Redis 字典
    Redis 链表实现
    Redis 事务
    winform,自定义文本框控件 实现文本框验证加水印功能
    WinForm中,每隔一段时间(参数)调用一次函数(使用定时器)
    GMap.Net 实现离线地图
  • 原文地址:https://www.cnblogs.com/tkt2016/p/8651403.html
Copyright © 2020-2023  润新知