程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> Emit學習-實戰篇-實現一個簡單的AOP框架(三)

Emit學習-實戰篇-實現一個簡單的AOP框架(三)

編輯:關於.NET

今天來介紹配置文件的定義和加載,先給出配置文件的內容,然後在詳細介紹裡面各節的含義,以及如何用程序加載配置文件,內容如下:

配置文件

<?xml version="1.0" encoding="utf-8" ?>
<AOP>
  <Regeisty>
    <IPreProcess>
      <Aspect id="AddPreProcessLog" value="YQL.TestProject:YQL.TestProject.AddPreProcessLog" isDefault="true"/>
      <Aspect id="VerifyPermission" value="YQL.AOP:YQL.AOP.VerifyPermission"/>
    </IPreProcess>
    <IPostProcess>
      <Aspect id="AddPostProcessLog" value="YQL.TestProject:YQL.TestProject.AddPostProcessLog" isDefault="true"/>
    </IPostProcess>
    <IExceptionHandler>
      <Aspect id="SimplyExceptionHandler" value="YQL.TestProject:YQL.TestProject.SimplyExceptionHandler" isDefault="true"/>
    </IExceptionHandler>
  </Regeisty>
  <Application>
    <Class id="YQL.TestProject:YQL.TestProject.Test">
      <Method id="Int32 Test4(System.String)">
        <IPreProcess>
          <Aspect id="AddPreProcessLog"/>
        </IPreProcess>
        <IPostProcess>
          <Aspect id="AddPostProcessLog"/>
          <Aspect id="TestException"/>
        </IPostProcess>
        <IExceptionHandler>
          <Aspect id="SimplyExceptionHandler"/>
        </IExceptionHandler>
      </Method>
    </Class>
  </Application>
</AOP>

配置文件中包含兩個部分分別是Regeisty節和Application節,Regeisty節包含了所有切面的實現類的定義,包含id,value和isDefault三個屬性:id表示這個實現的代號,在Application節可以通過這個代號來引用某個實現類,作為主鍵標識,必須唯一;value是這個實現類的具體信息,由所在的程序集和類的全名組成,中間用冒號分隔;isDefault屬性為可選,如果設置為true,則表示某個方法在沒有特殊的定義的情況下,使用這個實現類來實現某個具體的切面處理。Application節包含了所有需要特殊處理的方法的信息,首先是這個方法的所在類(類的信息描述與前面相同),然後是方法名,包括返回值類型和參數類型。按照我的設想,這個配置文件應該是通過一個配置工具,通過反射和用戶的一些選擇操作來生成的,當然現在這個配置工具還不存在,留待以後擴展。

接下來是配置文件的加載,我們定義了一個AopConfigManager類用來實現配置文件的加載以及維護,這裡面包含了兩個對外的方法分別用來初始化配置文件,和為方法植入時提供需要植入的切面信息,這兩個方法的實現如下:

Init

/// <summary>
/// 初始化配置文件信息
/// </summary>
/// <param name="configFilePath">配置文件路徑</param>
public static void Init(string configFilePath)
{
    XPathDocument document = new XPathDocument(configFilePath);
    XPathNavigator rootNavigator = document.CreateNavigator();
    //初始化各個方面的配置信息
    InitAspectInfo(rootNavigator);
    //初始化非默認行為的方法的方面配置信息
    InitClassInfo(rootNavigator);
}

這裡通過XPathNavigator來實現xml文件的讀取,然後分別初始化Regeisty節和Application節的內容,XPathNavigator類專門用來進行xml文件xpath形式的讀取,具體的使用可以參見msdn中的內容,我就不多說了 XPathNavigator 。

GetMethodAspectInfo

/// <summary>
/// 獲取指定方法的指定方面的信息
/// </summary>
/// <param name="methodInfo">方法的信息</param>
/// <param name="aspectType">指定的方面</param>
/// <returns></returns>
public static List<Type> GetMethodAspectInfo(MethodInfo methodInfo, AspectTypes aspectType)
{
    string methodName = methodInfo.ToString();
    string typeName = ReflectionHelper.GetTypeUniqueName(methodInfo.DeclaringType);
    List<Type> typeList = null;
    List<string> typeNameList = null;
    List<string> typeValueList = new List<string>();

    //讀獲取該方法的方面信息
    if (_classInfoDict.ContainsKey(typeName))
    {
        ClassTag classTag = _classInfoDict[typeName];
        typeNameList = classTag.GetAspectInfoList(methodName, aspectType);
    }

    string aspectName = EnumHelper.GetEnumDesceiption(aspectType);
    AspectTag aspectTag = _aspectInfoDict[aspectName];

    //沒有在配置文件中指定,則使用默認的配置
    if (null == typeNameList || 0 == typeNameList.Count)
    {
        typeNameList = aspectTag.GetDefaultAspectList();
    }

    foreach (string str in typeNameList)
    {
        typeValueList.Add(aspectTag.GetAspectTypeUniqueName(str));
    }

    typeList = ConvertToTypeList(typeValueList);

    return typeList;
}

該方法根據傳入的方法信息以及切面的枚舉項,從已經加載的配置文件中進行查找,如果找不到,則對起使用默認的配置,然後在將文本形式的類的信息通過反射轉換成Type類型。

類的實現細節主要是一些xml文件的操作,這裡就不貼出全部代碼了,如果有需要,我會在本系列結束後提供完整的源碼下載。另外從之前幾篇文章的回復當中看出,有些園友可能對我這個框架的期待過高了,其實這只是一個非常簡單的AOP框架,主要就是為了實踐一下之前所學習的Emit中的一些內容,然後實現了一個AOP框架所需要具有的幾個最基本的功能,甚至可能還稱不上是一個完整AOP框架,大家不要期待太多,不然真要把我慚愧死了!

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