我們通過一個計算A+B的動態類來演示如何為一個動態類添加屬性、構造函數 、方法,以及在方法中使用類中定義的屬性,按照慣例,我們先給出要實現的動 態類的C#代碼,然後再針對C#代碼給出相應的實現,代碼如下:
Add public class Add { private int _a = 0; public int A { get { return _a; } set { _a = value; } } private int _b = 0; public int B { get { return _b; } set { _b = value; } } public Add(int a, int b) { _a = a; _b = b; } public int Calc() { return _a + _b; }
前面的步驟和之前的斐波那契實現相同,這裡我們直接從屬性的定義開始。首 先,我們通過TypeBuilder對象的DefineField方法來定義私有字段_a和_b,並為 它們設置默認值0,代碼如下:
定義私有字段_a和_b
FieldBuilder fieldABuilder = typeBuilder.DefineField("_a", typeof (Int32), FieldAttributes.Private); FieldBuilder fieldBBuilder = typeBuilder.DefineField("_b", typeof (Int32), FieldAttributes.Private); fieldABuilder.SetConstant(0); fieldBBuilder.SetConstant(0);
然後我們通過TypeBuilder對象的DefineProperty方法分別定義屬性A、B;接 著再通過PropertyBuilder的SetGetMethod和SetSetMethod方法設置它們的get和 set方法,至於get和set方法的IL代碼的生成則和普通的Method定義相同,這裡只 列出屬性A的定義,屬性B與A相同,代碼如下:
定義公有屬性A和B
PropertyBuilder propertyABuilder = typeBuilder.DefineProperty("A", PropertyAttributes.None, typeof(Int32), null); PropertyBuilder propertyBBuilder = typeBuilder.DefineProperty("B", PropertyAttributes.None, typeof(Int32), null);
#region 定義屬性A的get和set方法
//定義屬性A的get方法 MethodBuilder getPropertyABuilder = typeBuilder.DefineMethod("get", MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig, typeof(Int32), Type.EmptyTypes); //生成屬性A的get方法的IL代碼,即返回私有字段_a ILGenerator getAIL = getPropertyABuilder.GetILGenerator(); getAIL.Emit(OpCodes.Ldarg_0); getAIL.Emit(OpCodes.Ldfld, fieldABuilder); getAIL.Emit(OpCodes.Ret); //定義屬性A的set方法 MethodBuilder setPropertyABuilder = typeBuilder.DefineMethod("set", MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig, null, new Type[] { typeof(Int32) }); //生成屬性A的set方法的IL代碼,即設置私有字段_a值為傳入的參數1的值 ILGenerator setAIL = setPropertyABuilder.GetILGenerator(); setAIL.Emit(OpCodes.Ldarg_0); setAIL.Emit(OpCodes.Ldarg_1); setAIL.Emit(OpCodes.Stfld, fieldABuilder); setAIL.Emit(OpCodes.Ret); //設置屬性A的get和set方法 propertyABuilder.SetGetMethod(getPropertyABuilder); propertyABuilder.SetSetMethod(setPropertyABuilder); #endregion
最後,我們來定義構造函數和Calc方法,構造函數的定義使用TypeBuilder的 DefineConstructor方法,獲得一個ConstructorBuilder對象,接下來就轉入到跟 普通的方法定義相同的步驟,代碼如下:
定義構造函數和方法
#region Step 5 定義構造函數
ConstructorBuilder constructorBuilder = typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, new Type[] { typeof(Int32), typeof(Int32) }); ILGenerator ctorIL = constructorBuilder.GetILGenerator(); //加載參數1填充到私有字段_a ctorIL.Emit(OpCodes.Ldarg_0); ctorIL.Emit(OpCodes.Ldarg_1); ctorIL.Emit(OpCodes.Stfld, fieldABuilder); //加載參數2填充到私有字段_b ctorIL.Emit(OpCodes.Ldarg_0); ctorIL.Emit(OpCodes.Ldarg_2); ctorIL.Emit(OpCodes.Stfld, fieldBBuilder); ctorIL.Emit(OpCodes.Ret); #endregion
#region Step 6 定義方法
MethodBuilder calcMethodBuilder = typeBuilder.DefineMethod("Calc", MethodAttributes.Public, typeof(Int32), Type.EmptyTypes); ILGenerator calcIL = calcMethodBuilder.GetILGenerator(); //加載私有字段_a calcIL.Emit(OpCodes.Ldarg_0); calcIL.Emit(OpCodes.Ldfld, fieldABuilder); //加載私有字段_b calcIL.Emit(OpCodes.Ldarg_0); calcIL.Emit(OpCodes.Ldfld, fieldBBuilder); //相加並返回結果 calcIL.Emit(OpCodes.Add); calcIL.Emit(OpCodes.Ret); #endregion
到這裡,我們終於完成了動態類的創建
本文配套源碼