一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - C# - 淺談C# AOP的簡單實現

淺談C# AOP的簡單實現

2022-02-25 14:24懶得安分 C#

這篇文章主要介紹了淺談C# AOP的簡單實現,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧

前言:為了弄清楚aop,博主也是拼了。這篇打算寫寫aop,說起aop,其實博主接觸這個概念也才幾個月,了解后才知道,原來之前自己寫的好多代碼原理就是基于aop的,比如mvc的過濾器filter,它里面的異常捕捉可以通過filterattribute,iexceptionfilter去處理,這兩個對象的處理機制內部原理應該就是aop,只不過之前沒有這個概念罷了。

一、aop概念

老規矩,還是先看官方解釋:aop(aspect-oriented programming,面向切面的編程),它是可以通過預編譯方式和運行期動態代理實現在不修改源代碼的情況下給程序動態統一添加功能的一種技術。它是一種新的方法論,它是對傳統oop編程的一種補充。oop是關注將需求功能劃分為不同的并且相對獨立,封裝良好的類,并讓它們有著屬于自己的行為,依靠繼承和多態等來定義彼此的關系;aop是希望能夠將通用需求功能從不相關的類當中分離出來,能夠使得很多類共享一個行為,一旦發生變化,不必修改很多類,而只需要修改這個行為即可。aop是使用切面(aspect)將橫切關注點模塊化,oop是使用類將狀態和行為模塊化。在oop的世界中,程序都是通過類和接口組織的,使用它們實現程序的核心業務邏輯是十分合適。但是對于實現橫切關注點(跨越應用程序多個模塊的功能需求)則十分吃力,比如日志記錄,權限驗證,異常攔截等。

博主的理解:aop就是將公用功能提取出來,如果以后公用功能的需求發生變化,只需要改動公用的模塊的代碼即可,多個調用的地方則不需要改動。所謂面向切面,就是只關注通用功能,而不關注業務邏輯。實現方式一般是通過攔截。比如,我們隨便一個web項目基本都有的權限驗證功能,進入每個頁面前都會校驗當前登錄用戶是否有權限查看該界面,我們不可能說在每個頁面的初始化方法里面都去寫這段驗證的代碼,這個時候我們的aop就派上用場了,aop的機制是預先定義一組特性,使它具有攔截方法的功能,可以讓你在執行方法之前和之后做你想做的業務,而我們使用的時候只需要的對應的方法或者類定義上面加上某一個特性就好了。

二、使用aop的優勢

博主覺得它的優勢主要表現在:

1、將通用功能從業務邏輯中抽離出來,可以省略大量重復代碼,有利于代碼的操作和維護。

2、在軟件設計時,抽出通用功能(切面),有利于軟件設計的模塊化,降低軟件架構的復雜度。也就是說通用的功能都是一個單獨的模塊,在項目的主業務里面是看不到這些通用功能的設計代碼的。

三、aop的簡單應用

為了說明aop的工作原理,博主打算先從一個簡單的例子開始,通過靜態攔截的方式來了解aop是如何工作的。

1、靜態攔截

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
public class order
  {
    public int id { set; get; }
    public string name { set; get; }
    public int count { set; get; }
    public double price { set; get; }
    public string desc { set; get; }
  }
 
  public interface iorderprocessor
  {
    void submit(order order);
  }
  public class orderprocessor : iorderprocessor
  {
    public void submit(order order)
    {
      console.writeline("提交訂單");
    }
  }
 
  public class orderprocessordecorator : iorderprocessor
  {
    public iorderprocessor orderprocessor { get; set; }
    public orderprocessordecorator(iorderprocessor orderprocessor)
    {
      orderprocessor = orderprocessor;
    }
    public void submit(order order)
    {
      preproceed(order);
      orderprocessor.submit(order);
      postproceed(order);
    }
    public void preproceed(order order)
    {
      console.writeline("提交訂單前,進行訂單數據校驗....");
      if (order.price < 0)
      {
        console.writeline("訂單總價有誤,請重新核對訂單。");
      }
    }
 
    public void postproceed(order order)
    {
      console.writeline("提交帶單后,進行訂單日志記錄......");
      console.writeline(datetime.now.tostring("yyyy-mm-dd hh:mm:ss") + "提交訂單,訂單名稱:" + order.name + ",訂單價格:" + order.price);
    }
  }

調用代碼:

?
1
2
3
4
5
6
7
static void main(string[] args)
    {
      order order = new order() { id = 1, name = "lee", count = 10, price = 100.00, desc = "訂單測試" };
      iorderprocessor orderprocessor = new orderprocessordecorator(new orderprocessor());
      orderprocessor.submit(order);
      console.readline();
    }

得到結果:

淺談C# AOP的簡單實現

上面我們模擬訂單提交的例子,在提交一個訂單前,我們需要做很多的準備工作,比如數據有效性校驗等;訂單提交完成之后,我們還需要做日志記錄等。上面的代碼很簡單,沒有任何復雜的邏輯,從上面的代碼可以看出,我們通過靜態植入的方式手動在執行方法前和執行方法后讓它做一些我們需要的功能。aop的實現原理應該也是如此,只不過它幫助我們做了方法攔截,幫我們省去了大量重復代碼,我們要做的僅僅是寫好攔截前和攔截后需要處理的邏輯。

2、動態代理

了解了靜態攔截的例子,你是否對aop有一個初步的認識了呢。下面我們就來到底aop該如何使用。按照園子里面很多牛人的說法,aop的實現方式大致可以分為兩類:動態代理和il 編織兩種方式。博主也不打算照本宣科,分別拿demo來說話吧。下面就以兩種方式各選一個代表框架來說明。

動態代理方式,博主就以微軟企業庫(ms enterprise library)里面的piab(policy injection application block)框架來作說明。

首先需要下載以下幾個dll,然后添加它們的引用。

淺談C# AOP的簡單實現

然后定義對應的handler

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
public class user
  {
    public string name { set; get; }
    public string password { set; get; }
  }
 
  #region 1、定義特性方便使用
  public class loghandlerattribute : handlerattribute
  {
    public string loginfo { set; get; }
    public int order { get; set; }
    public override icallhandler createhandler(iunitycontainer container)
    {
      return new loghandler() { order = this.order, loginfo = this.loginfo };
    }
  }
  #endregion
 
  #region 2、注冊對需要的handler攔截請求
  public class loghandler : icallhandler
  {
    public int order { get; set; }
    public string loginfo { set; get; }
 
    //這個方法就是攔截的方法,可以規定在執行方法之前和之后的攔截
    public imethodreturn invoke(imethodinvocation input, getnexthandlerdelegate getnext)
    {
      console.writeline("loginfo內容" + loginfo);
      //0.解析參數
      var arrinputs = input.inputs;
      if (arrinputs.count > 0)
      {
        var ousertest1 = arrinputs[0] as user;
      }
      //1.執行方法之前的攔截
      console.writeline("方法執行前攔截到了");
      //2.執行方法
      var messagereturn = getnext()(input, getnext);
 
      //3.執行方法之后的攔截
      console.writeline("方法執行后攔截到了");
      return messagereturn;
    }
  }
  #endregion
 
  #region 3、用戶定義接口和實現
  public interface iuseroperation
  {
    void test(user ouser);
    void test2(user ouser, user ouser2);
  }
 
 
  //這里必須要繼承這個類marshalbyrefobject,否則報錯
  public class useroperation : marshalbyrefobject, iuseroperation
  {
    private static useroperation ouseropertion = null;
    public useroperation()
    {
      //ouseropertion = policyinjection.create<useroperation>();
    }
 
    //定義單例模式將policyinjection.create<useroperation>()產生的這個對象傳出去,這樣就避免了在調用處寫這些東西
    public static useroperation getinstance()
    {
      if (ouseropertion == null)
        ouseropertion = policyinjection.create<useroperation>();
 
      return ouseropertion;
    }
    //調用屬性也會攔截
    public string name { set; get; }
 
    //[loghandler],在方法上面加這個特性,只對此方法攔截
    [loghandler(loginfo = "test的日志為aaaaa")]
    public void test(user ouser)
    {
      console.writeline("test方法執行了");
    }
 
    [loghandler(loginfo = "test2的日志為bbbbb")]
    public void test2(user ouser, user ouser2)
    {
      console.writeline("test2方法執行了");
    }
  }
  #endregion

最后我們來看調用的代碼:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
static void main(string[] args)
    {
      try
      {
        var ousertest1 = new user() { name = "test2222", password = "yxj" };
        var ousertest2 = new user() { name = "test3333", password = "yxj" };
        var ouser = useroperation.getinstance();
        ouser.test(ousertest1);
        ouser.test2(ousertest1,ousertest2);
      }
      catch (exception ex)
      {
        //throw;
      }
    }

得到結果如下:

淺談C# AOP的簡單實現

我們來看執行test()方法和test2()方法時候的順序。

淺談C# AOP的簡單實現

由于test()和test2()方法上面加了loghander特性,這個特性里面定義了aop的handler,在執行test和test2方法之前和之后都會進入invoke()方法里面。其實這就是aop的意義所在,將切面的通用功能在統一的地方處理,在主要邏輯里面直接用過特性使用即可。

3、il編織

靜態織入的方式博主打算使用postsharp來說明,一來這個使用起來簡單,二來項目中用過這種方式。

postsharp從2.0版本就開始收費了。為了說明aop的功能,博主下載了一個免費版本的安裝包,使用postsharp與其它框架不太一樣的是一定要下載安裝包安裝,只引用類庫是不行的,因為上文說過,aop框架需要為編譯器或運行時添加擴展。使用步驟如下:

(1)下載postsharp安裝包,安裝。

(2)在需要使用aop的項目中添加postsharp.dll這個dll的引用。

(3)定義攔截的方法:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
[serializable]
  public class testaop : postsharp.aspects.onmethodboundaryaspect
  {
     //發生異常時進入此方法
    public override void onexception(methodexecutionargs args)
    {
      base.onexception(args);
    }
 
     //執行方法前執行此方法
    public override void onentry(methodexecutionargs args)
    {
      base.onentry(args);
    }
 
     //執行方法后執行此方法
    public override void onexit(methodexecutionargs args)
    {
      base.onexit(args);
    }
  }

注意這里的testaop這個類必須要是可序列化的,所以要加上[serializable]特性

(4)在需要攔截功能的地方使用。

在類上面加特性攔截,此類下面的所有的方法都會具有攔截功能。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
[testaop]public class impc_tm_plant : ifc_tm_plant
  {
    /// <summary>
    /// 獲取或設置服務接口。
    /// </summary>
    private ic_tm_plantservice service { get; set; }
    
    public ilist<dto_tm_plant> find()
    {
      dto_tm_plant otest = null;
      otest.name_c = "test";//異常,會進入onexception方法
        return service.findall();
     }
  }

方法上面加特性攔截,只會攔截此方法。

?
1
2
3
4
5
6
7
[testaop]
    public ilist<dto_tm_plant> find()
    {
      dto_tm_plant otest = null;
      otest.name_c = "test";
      return service.findall();
    }

有沒有感覺很簡單,很強大,其實這一簡單應用,解決我們常見的日志、異常、權限驗證等功能簡直太小菜一碟了。當然postsharp可能還有許多更加高級的功能,有興趣可以深究下。

4、mvc里面的filter

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class aopfilterattribute : actionfilterattribute, iexceptionfilter
  {
 
    public void onexception(exceptioncontext filtercontext)
    {
      throw new system.notimplementedexception();
    }
    public override void onactionexecuting(actionexecutingcontext filtercontext)
    {
      
      base.onactionexecuting(filtercontext);
    }
 
    public override void onactionexecuted(actionexecutedcontext filtercontext)
    {
      base.onactionexecuted(filtercontext);
    }
  }

在controller里面使用該特性:

?
1
2
3
4
5
6
7
8
9
10
[aopfilter]
    public jsonresult geteditmodel(string strtype)
    {
      var lstres = new list<list<dragelementprop>>();
      var lstrespage = new list<pageproperty>();
 
       //.........todo
 
      return json(new { lstdataattr = lstres, pageattr = lstrespage, lstjsconnections = lstjsplumblines }, jsonrequestbehavior.allowget);
    }

調試可知,在執行geteditmodel(string strtype)方法之前,會先執行onactionexecuting()方法,geteditmodel(string strtype)之后,又會執行onactionexecuted()方法。這在我們mvc里面權限驗證、錯誤頁導向、日志記錄等常用功能都可以方便解決。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。

原文鏈接:http://www.cnblogs.com/landeanfen/p/4782370.html

延伸 · 閱讀

精彩推薦
  • C#深入解析C#中的交錯數組與隱式類型的數組

    深入解析C#中的交錯數組與隱式類型的數組

    這篇文章主要介紹了深入解析C#中的交錯數組與隱式類型的數組,隱式類型的數組通常與匿名類型以及對象初始值設定項和集合初始值設定項一起使用,需要的...

    C#教程網6172021-11-09
  • C#C#設計模式之Visitor訪問者模式解決長隆歡樂世界問題實例

    C#設計模式之Visitor訪問者模式解決長隆歡樂世界問題實例

    這篇文章主要介紹了C#設計模式之Visitor訪問者模式解決長隆歡樂世界問題,簡單描述了訪問者模式的定義并結合具體實例形式分析了C#使用訪問者模式解決長...

    GhostRider9502022-01-21
  • C#C# 實現對PPT文檔加密、解密及重置密碼的操作方法

    C# 實現對PPT文檔加密、解密及重置密碼的操作方法

    這篇文章主要介紹了C# 實現對PPT文檔加密、解密及重置密碼的操作方法,非常不錯,具有參考借鑒價值,需要的朋友可以參考下...

    E-iceblue5012022-02-12
  • C#C#實現XML文件讀取

    C#實現XML文件讀取

    這篇文章主要為大家詳細介紹了C#實現XML文件讀取的相關代碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下...

    Just_for_Myself6702022-02-22
  • C#C#通過KD樹進行距離最近點的查找

    C#通過KD樹進行距離最近點的查找

    這篇文章主要為大家詳細介紹了C#通過KD樹進行距離最近點的查找,具有一定的參考價值,感興趣的小伙伴們可以參考一下...

    帆帆帆6112022-01-22
  • C#Unity3D實現虛擬按鈕控制人物移動效果

    Unity3D實現虛擬按鈕控制人物移動效果

    這篇文章主要為大家詳細介紹了Unity3D實現虛擬按鈕控制人物移動效果,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一...

    shenqingyu060520232410972022-03-11
  • C#WPF 自定義雷達圖開發實例教程

    WPF 自定義雷達圖開發實例教程

    這篇文章主要介紹了WPF 自定義雷達圖開發實例教程,本文介紹的非常詳細,具有參考借鑒價值,需要的朋友可以參考下...

    WinterFish13112021-12-06
  • C#C#裁剪,縮放,清晰度,水印處理操作示例

    C#裁剪,縮放,清晰度,水印處理操作示例

    這篇文章主要為大家詳細介紹了C#裁剪,縮放,清晰度,水印處理操作示例,具有一定的參考價值,感興趣的小伙伴們可以參考一下...

    吳 劍8332021-12-08
主站蜘蛛池模板: 逼逼爱 | 91免费在线| 欧美添下面视频免费观看 | 美国xxnx| 国产精品边做边接电话在线观看 | 特黄特色大片免费高清视频 | 日本天堂视频在线观看 | 国产综合视频 | 国产小视频在线播放 | 亚洲国产精品一区二区三区久久 | 国产精品免费小视频 | 青青草在线播放 | 欧美一级精品 | 免费国产影视观看网站入口 | 美琪美腿白丝交小说 | 香蕉久久久久 | 久久无码AV亚洲精品色午夜麻豆 | 精品久久免费视频 | 五月激激激综合网色播免费 | 91香蕉在线| 日本javhd | 欧美日韩国产中文字幕 | 四虎影视在线看免费 720p | 99久久精品无码一区二区毛片 | 国产普通话对白露脸流出 | 国产精品免费_区二区三区观看 | 日本午夜小视频 | 美女扒开腿让男生桶爽漫画 | 青草碰人人澡人人澡 | 成人尤物 | 免费精品在线视频 | 国产三级跑 | 性夜影院午夜看片 | 青草视频在线观看免费资源 | 欧美日韩一区二区综合在线视频 | 呜呜别塞了啊抽插 | 二次元美女扒开内裤露尿口 | 极品丝袜乱系列在线阅读 | 果冻传媒在线视频观看免费 | 任我淫 | 亚洲福利一区二区精品秒拍 |