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

 

posted @ 2018-03-26 15:31  Z语言  阅读(372)  评论(0编辑  收藏  举报