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;
}
}
}
}
第一步,生成一个字段
生成字段用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);
}
}
}