程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> IL接口和類的屬性,IL接口屬性

IL接口和類的屬性,IL接口屬性

編輯:關於.NET

IL接口和類的屬性,IL接口屬性


   上一篇文章學習了IL的入門,接下來我們再通過兩個例子來了解下類的屬性、構造函數以及接口的使用

一、類的屬性、構造函數

1、先看下我們要構建的類的C#代碼,然後再進行IL的實現,示例代碼如下:

    [Serializable]
    public class Dynamic
    {
        public int _a = 0;
        public const string ConstField = "const";

        /// <summary>
        /// 定義屬性
        /// </summary>
        public int A { get; set; }

        /// <summary>
        /// 構造函數
        /// </summary>
        /// <param name="num"></param>
        public Dynamic(int num)
        {
            this.A = num;
        }

        public int Add(int num)
        {
            return this.A + num;
        }
    }
View Code

2、通過以上代碼我們可以根據要求先定義字段_a、常量ConstField(在構造函數過程中未使用到,幫組了解類屬性的創建)以及給類加上序列化標簽,屬性可以通過TypeBuilder的DefineField創建,而序列化標簽需要通過TypeBuilder的CustomAttributeBuilder去創建,示例代碼如下:

            //定義類可序列化
            CustomAttributeBuilder serializable = new CustomAttributeBuilder(typeof(SerializableAttribute).GetConstructor(Type.EmptyTypes), new Type[] { });
            typeBuilder.SetCustomAttribute(serializable);

            //定義常量
            FieldBuilder fieldConst = typeBuilder.DefineField("ConstField", typeof(string), FieldAttributes.Static | FieldAttributes.Public | FieldAttributes.Literal);
            fieldConst.SetConstant("const");

            //定義字段_a
            FieldBuilder aField = typeBuilder.DefineField("_a", typeof(int), FieldAttributes.Private);
            aField.SetConstant(0);
View Code

3、通過TypeBuilder的DefineProperty定義屬性A,通過CustomAttributeBuilder給屬性添加對應的標簽,示例代碼如下:

            //定義屬性A
            PropertyBuilder propertyABuilder = typeBuilder.DefineProperty("A", PropertyAttributes.None, typeof(int), null);
            CustomAttributeBuilder desAttributeBuilder = new CustomAttributeBuilder(typeof(DescriptionAttribute).GetConstructor(new Type[] { typeof(string) }), new object[] { "屬性A" });
            propertyABuilder.SetCustomAttribute(desAttributeBuilder);//字段描述
View Code

4、定義A屬性的get方法和set方法,get和set方法和普通的方法創建相同,用TypeBuilder的DefineMethod創建。示例代碼如下:

            //定義屬性get方法
            MethodBuilder methodABuilder = typeBuilder.DefineMethod("get", MethodAttributes.Public, typeof(Int32), Type.EmptyTypes);
            ILGenerator GetIL = methodABuilder.GetILGenerator();
            GetIL.Emit(OpCodes.Ldarg_0);
            GetIL.Emit(OpCodes.Ldfld, aField);
            GetIL.Emit(OpCodes.Ret);
            propertyABuilder.SetGetMethod(methodABuilder);

            //定義屬性set方法
            MethodBuilder methodBBuilder = typeBuilder.DefineMethod("set", MethodAttributes.Public, typeof(Int32), new Type[] { typeof(Int32) });
            ILGenerator SetIL = methodBBuilder.GetILGenerator();
            SetIL.Emit(OpCodes.Ldarg_0);
            SetIL.Emit(OpCodes.Ldarg_1);
            SetIL.Emit(OpCodes.Stfld, aField);
            SetIL.Emit(OpCodes.Ret);
            propertyABuilder.SetSetMethod(methodBBuilder);
View Code

5、構造函數的創建,構造函數是通過TypeBuilder的DefineConstructor去獲取,構造函數包含一個參數並賦值給_a,示例代碼如下:

            //定義構造函數
            ConstructorBuilder constructorBuilder = typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, new Type[] { typeof(Int32) });

            ILGenerator constructorIL = constructorBuilder.GetILGenerator();
            constructorIL.Emit(OpCodes.Ldarg_0);
            constructorIL.Emit(OpCodes.Ldarg_1);
            constructorIL.Emit(OpCodes.Stfld, aField);
            constructorIL.Emit(OpCodes.Ret);
View Code

6、最後是定義方法。

            //定義方法
            MethodBuilder methodAddBuild = typeBuilder.DefineMethod("Add", MethodAttributes.Public, typeof(Int32), new Type[] { typeof(int) });
            ILGenerator addIL = methodAddBuild.GetILGenerator();
            addIL.Emit(OpCodes.Ldarg_0);
            addIL.Emit(OpCodes.Ldfld, aField);
            addIL.Emit(OpCodes.Ldarg_1);
            addIL.Emit(OpCodes.Add);
            addIL.Emit(OpCodes.Ret);
View Code

到這一步一個動態類包含的屬性、構造函數以及方法就創建完成。可以借助reflector看下生成的結果。如下:

public int A { get; set; }
換成
public int A5
{
get { return _a; }
set { _a = value; }
}
比較容易理解_a的存在

 二、接口的實現

1、首先我們看下我們要實現一個什麼樣的接口,先看下構建類的C#代碼,示例代碼如下:

    public class Mail : IMail
    {

        public string SendMail()
        {
            return "Send Success";
        }
    }

    public interface IMail
    {
        string SendMail();
    }
View Code

2、實現接口,接口我們直接用IMail這個。就不用IL去創建了,首先我們創建一個typeBuilder,指定繼承接口IMail,可以用AddInterfaceImplementation來進行操作。示例代碼如下:

            //定義類型
            TypeBuilder typeBuilder = moduleBuilder.DefineType(name, TypeAttributes.Public);
            typeBuilder.AddInterfaceImplementation(typeof(IMail));
View Code

3、實現接口。接口實現方法要怎麼定義在不清楚的情況下可以用reflector反編譯一個實現接口的方法來查看一下,觀察一下方法需要哪些MethodAttributes屬性。

通過以上信息可以定義接口實現的方法,接口實現就和之前例子定義的方法實現一樣。示例代碼如下:

            MethodBuilder sendMailBuilder = typeBuilder.DefineMethod("SendMail", MethodAttributes.Public | MethodAttributes.ReuseSlot | MethodAttributes.Virtual | MethodAttributes.HideBySig, typeof(string), null);
            //定義接口
            ILGenerator mailIL = sendMailBuilder.GetILGenerator();
            LocalBuilder resultStr = mailIL.DeclareLocal(typeof(String));
            mailIL.Emit(OpCodes.Nop);
            mailIL.Emit(OpCodes.Ldstr, "Send Success1");
            mailIL.Emit(OpCodes.Stloc_0);
            mailIL.Emit(OpCodes.Ldloc_0);
            mailIL.Emit(OpCodes.Ret);
View Code

實現後通過IL查看的代碼如下:

  通過反編譯發現,接口實現是帶有override關鍵字的。而在定義實現方法時候如果不帶上virtual屬性又會提示接口未實現。也請知道的朋友解決下我的疑惑。

  通過這篇文章我們了解到了動態類的創建,也了解到了接口的使用。從這兩個示例其實可以拓展出很多的東西比如繼承、屬性綁定自定義標簽、虛方法的重寫......這些東西也是需要不斷學習才能了解。在IL這塊的學習還有比較多的不懂在之後的學習再分享。
示例代碼下載:IL-3

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