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,newType[] { 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
MSIL實用指南-生成屬性