程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> Emit學習-基礎篇-為動態類添加屬性、構造函數、方法

Emit學習-基礎篇-為動態類添加屬性、構造函數、方法

編輯:關於.NET

我們通過一個計算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

到這裡,我們終於完成了動態類的創建

本文配套源碼

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved