我們通過一個計算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
到這裡,我們終於完成了動態類的創建
本文配套源碼