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

PostSharp的反編譯分析

編輯:關於.NET

前段時間做一個權限系統,在考慮日志、異常接管、事務、緩存等等一些橫向組件的架構分析,自然就想用AOP技術實現;這兩天又重 新學習研究了PostSharp的架構與實現思想,將其融入現有框架;

由於采用 MSIL Injection,因此靜態代碼注入的執行效率要高於使用 Reflection Emit。 使用 MSBuild Task,使得開發人員可以像 使用編譯器內置 Attribute 那樣使用 AOP。 可以攔截任意方法,而 Dynamic Proxy 方式的 AOP 往往采取繼承方式來攔截 Virtual 方法 。 擁有更多的控制權。包括中斷執行流程,修改參數和返回值等等。 還可以攔截 Field Access、Exception 等操作。 無需將對象創建 代碼改成 "new proxy()",更加透明。 可以使用通配符進行多重攔截匹配。 靜態注入帶來的問題更多的是注入代碼的質量和調試復雜度 。 另外有一老外的Using AOP and PostSharp to Enhance Your CodeAB兩部分,相當精彩,本文就是在參考這兩篇好文的基礎上做的。

我們假設有這麼個場景,其實這也是實際業務中很常見的處理方式:有一定單管理模塊,具備新增、刪除兩功能,我們在新增刪除的時 候必須校驗權限,在刪除的時候還必須記錄日志,出現異常了還必須捕捉並記錄異常;

按以前的寫法我們可能很麻煩,我們要如此這般的寫:

01 public class XOrders
02     {
03         public bool Add(string id, string orderName)
04         {
05             try
06             {
07                 if (User.AddEnable)
08                 {
09                     //TODO:新增訂單的實現
10                     Console.WriteLine("正在執行新增訂單方法的操作,回車繼續……");
11                     Console.ReadLine();
12                     Console.WriteLine("您添加訂單成功:編號:{0},名稱:{1}", id,  orderName);
13                     return true;
14                 }
15                 else
16                 {
17                     //
18                 }
19             }
20             catch (Exception)
21             {
22                 //TODO:記錄異常的實現
23                 throw;
24             }
25
26             return true;
27
28         }
29
30         public bool Delete(string id)
31         {
32             try
33             {
34                 if (User.DeleteEnable)
35                 {
36                     //TODO:刪除訂單的實現
37                     Console.WriteLine("您刪除訂單成功:編號:{0}", id);
38                 }
39                 else
40                 {
41                     //
42                 }
43
44             }
45             catch (Exception)
46             {
47                 //TODO:記錄異常的實現
48                 throw;
49             }
50
51             return true;
52         }

這種寫的弊端我就不多說了,有很多先驅都闡述過……

我要演示的是采用AOP技術的框架原型實現:

首先我們應該安裝PostSharp(一定要安裝要不能沒辦法注入處理代碼)

然後我們實現Orders對象

01 using System;
02
03 namespace PostSharp.Demo
04 {
05     public class Orders
06     {
07         [Permission]
08         [Exception]
09         public bool Add(string id, string orderName)
10         {
11             Console.WriteLine("正在執行新增訂單方法的操作,回車繼續……");
12             Console.ReadLine();
13             Console.WriteLine("您添加訂單成功:編號:{0},名稱:{1}", id, orderName);
14             return true;
15         }
16
17         [Logger]
18         [Permission]
19         [Exception]
20         public bool Delete(string id)
21         {
22             Console.WriteLine("您刪除訂單成功:編號:{0}", id);
23
24             return true;
25         }
26     }
27 }

當然還要模擬一個用戶資格認證

01 namespace PostSharp.Demo
02 {
03     /// <summary>
04     /// 靜態的用戶對象,用於存放當前登錄用戶,成員資格
05     /// </summary>
06     public static class User
07     {
08         private static string _userId;
09
10         public static string UserId
11         {
12             get { return _userId; }
13             set { _userId = value; }
14         }
15
16         public static bool AddEnable
17         {
18             get
19             {
20                 return (_userId.ToLower() == "admin");
21             }
22         }
23
24         public static bool DeleteEnable
25         {
26             get
27             {
28                 return (_userId.ToLower() == "admin");
29             }
30         }
31     }
32 }

再然後我們實現權限控制方面PermissionAttribute,日志方面LoggerAttribute,異常處理方面ExceptionAttribute……

PermissionAttribute

01 using System;
02 using PostSharp.Laos;
03
04 namespace PostSharp.Demo
05 {
06     [Serializable]
07     [global::System.AttributeUsage(AttributeTargets.All, Inherited = true, AllowMultiple = false)]
08     public class PermissionAttribute : OnMethodBoundaryAspect
09     {
10         public override void OnEntry(MethodExecutionEventArgs eventArgs)
11         {
12             if (!User.AddEnable)
13             {
14                 Console.WriteLine("用戶:【{0}】沒有權限:【{1}】", User.UserId,  eventArgs.Method);
15                 eventArgs.FlowBehavior = FlowBehavior.Return;
16             }
17
18         }
19     }
20 }
21
22 LoggerAttribute
23
24 using System;
25 using PostSharp.Laos;
26
27 namespace PostSharp.Demo
28 {
29     [Serializable]
30     [global::System.AttributeUsage(AttributeTargets.All, Inherited = true, AllowMultiple = false)]
31     public sealed class LoggerAttribute : OnMethodInvocationAspect
32     {
33         public override void OnInvocation(MethodInvocationEventArgs eventArgs)
34         {
35             DateTime time = DateTime.Now;
36             string log = "

然後再用控制台程序測試下能不能成功

01 Orders order = new Orders();
02             Console.WriteLine("請輸入用戶名:");
03             User.UserId = Console.ReadLine();
04             Console.WriteLine("請輸入密碼:");
05             Console.ReadLine();
06             string id;
07
08             LRedo:
09             Console.WriteLine("請輸入您要執行的操作:新增(A),刪除(D),退出(X)");
10
11             string opt = Console.ReadLine();
12
13             if (opt.ToLower() == "a")
14             {
15                 Console.WriteLine("請輸入訂單編號:");
16                 id = Console.ReadLine();
17
18                 Console.WriteLine("請輸入訂單名稱:");
19                 string name = Console.ReadLine();
20                 order.Add(id, name);
21             }
22             else if (opt.ToLower() == "d")
23             {
24                 Console.WriteLine("請輸入訂單編號:");
25                 id = Console.ReadLine();
26                 order.Delete(id);
27             }
28             else if (opt.ToLower() == "x")
29             {
30             }
31             else
32             {
33                 Console.WriteLine("您的輸入不正確,請重新輸入!");
34                 goto LRedo;
35             }
36
37             Console.WriteLine("按任意鍵退出……");
38             Console.ReadLine();

寫完這些我們再反編譯一下生成的exe文件,發現裡面的Orders成了這模樣了

001 public class Orders
002 {
003     // Methods
004     static Orders()
005     {
006         if (!~PostSharp~Laos~Implementation.initialized)
007         {
008             LaosNotInitializedException.Throw();
009         }
010         ~PostSharp~Laos~Implementation.~targetMethod~1 = methodof(Orders.Add);
011         ~PostSharp~Laos~Implementation.~aspect~1.RuntimeInitialize (~PostSharp~Laos~Implementation.~targetMethod~1);
012         ~PostSharp~Laos~Implementation.~targetMethod~5 = methodof(Orders.Delete);
013         ~PostSharp~Laos~Implementation.~aspect~5.RuntimeInitialize (~PostSharp~Laos~Implementation.~targetMethod~5);
014         ~PostSharp~Laos~Implementation.~targetMethod~4 = methodof(Orders.Delete);
015         ~PostSharp~Laos~Implementation.~aspect~4.RuntimeInitialize (~PostSharp~Laos~Implementation.~targetMethod~4);
016         ~PostSharp~Laos~Implementation.~targetMethod~3 = methodof(Orders.Add);
017         ~PostSharp~Laos~Implementation.~aspect~3.RuntimeInitialize (~PostSharp~Laos~Implementation.~targetMethod~3);
018         ~PostSharp~Laos~Implementation.~targetMethod~2 = methodof(Orders.Delete);
019         ~PostSharp~Laos~Implementation.~aspect~2.RuntimeInitialize (~PostSharp~Laos~Implementation.~targetMethod~2);
020     }
021
022     private bool ~Delete(string id)
023     {
024         Console.WriteLine("您刪除訂單成功:編號:{0}", id);
025         return true;
026     }
027
028     public bool Add(string id, string orderName)
029     {
030         bool ~returnValue~1;
031         MethodExecutionEventArgs ~laosEventArgs~7;
032         try
033         {
034             object[] ~arguments~6 = new object[] { id, orderName };
035             ~laosEventArgs~7 = new MethodExecutionEventArgs(methodof(Orders.Add, Orders), this,  ~arguments~6);
036             ~PostSharp~Laos~Implementation.~aspect~1.OnEntry(~laosEventArgs~7);
037             if (~laosEventArgs~7.FlowBehavior == FlowBehavior.Return)
038             {
039                 return (bool) ~laosEventArgs~7.ReturnValue;
040             }
041             try
042             {
043                 Console.WriteLine("正在執行新增訂單方法的操作,回車繼續……");
044                 Console.ReadLine();
045                 Console.WriteLine("您添加訂單成功:編號:{0},名稱:{1}", id, orderName);
046                 ~returnValue~1 = true;
047             }
048             catch (Exception ~exception~2)
049             {
050                 object[] ~arguments~3 = new object[] { id, orderName };
051                 MethodExecutionEventArgs ~laosEventArgs~4 = new MethodExecutionEventArgs (methodof(Orders.Add, Orders), this, ~arguments~3);
052                 ~laosEventArgs~4.Exception = ~exception~2;
053                 ~PostSharp~Laos~Implementation.~aspect~3.OnException(~laosEventArgs~4);
054                 switch (~laosEventArgs~4.FlowBehavior)
055                 {
056                     case FlowBehavior.Continue:
057                         goto Label_0145;
058
059                     case FlowBehavior.Return:
060                         ~returnValue~1 = (bool) ~laosEventArgs~4.ReturnValue;
061                         goto Label_0145;
062                 }
063                 throw;
064             }
065         Label_0145:
066             ~laosEventArgs~7.ReturnValue = ~returnValue~1;
067             ~PostSharp~Laos~Implementation.~aspect~1.OnSuccess(~laosEventArgs~7);
068             ~returnValue~1 = (bool) ~laosEventArgs~7.ReturnValue;
069         }
070         catch (Exception ~exception~5)
071         {
072             ~laosEventArgs~7.Exception = ~exception~5;
073             ~PostSharp~Laos~Implementation.~aspect~1.OnException(~laosEventArgs~7);
074             switch (~laosEventArgs~7.FlowBehavior)
075             {
076                 case FlowBehavior.Continue:
077                     return ~returnValue~1;
078
079                 case FlowBehavior.Return:
080                     return (bool) ~laosEventArgs~7.ReturnValue;
081             }
082             throw;
083         }
084         finally
085         {
086             ~laosEventArgs~7.ReturnValue = ~returnValue~1;
087             ~PostSharp~Laos~Implementation.~aspect~1.OnExit(~laosEventArgs~7);
088             ~returnValue~1 = (bool) ~laosEventArgs~7.ReturnValue;
089         }
090         return ~returnValue~1;
091     }
092
093     [DebuggerNonUserCode]
094     public bool Delete(string id)
095     {
096         bool ~returnValue~2;
097         MethodExecutionEventArgs ~laosEventArgs~8;
098         try
099         {
100             object[] ~arguments~7 = new object[] { id };
101             ~laosEventArgs~8 = new MethodExecutionEventArgs(methodof(Orders.Delete, Orders),  this, ~arguments~7);
102             ~PostSharp~Laos~Implementation.~aspect~2.OnEntry(~laosEventArgs~8);
103             if (~laosEventArgs~8.FlowBehavior == FlowBehavior.Return)
104             {
105                 return (bool) ~laosEventArgs~8.ReturnValue;
106             }
107             try
108             {
109                 Delegate delegateInstance = new ~PostSharp~Laos~Implementation.~delegate~0 (this.~Delete);
110                 object[] arguments = new object[] { id };
111                 MethodInvocationEventArgs eventArgs = new MethodInvocationEventArgs (delegateInstance, arguments);
112                 ~PostSharp~Laos~Implementation.~aspect~5.OnInvocation(eventArgs);
113                 ~returnValue~2 = (bool) eventArgs.ReturnValue;
114             }
115             catch (Exception ~exception~3)
116             {
117                 object[] ~arguments~4 = new object[] { id };
118                 MethodExecutionEventArgs ~laosEventArgs~5 = new MethodExecutionEventArgs (methodof(Orders.Delete, Orders), this, ~arguments~4);
119                 ~laosEventArgs~5.Exception = ~exception~3;
120                 ~PostSharp~Laos~Implementation.~aspect~4.OnException(~laosEventArgs~5);
121                 switch (~laosEventArgs~5.FlowBehavior)
122                 {
123                     case FlowBehavior.Continue:
124                         goto Label_0160;
125
126                     case FlowBehavior.Return:
127                         ~returnValue~2 = (bool) ~laosEventArgs~5.ReturnValue;
128                         goto Label_0160;
129                 }
130                 throw;
131             }
132         Label_0160:
133             ~laosEventArgs~8.ReturnValue = ~returnValue~2;
134             ~PostSharp~Laos~Implementation.~aspect~2.OnSuccess(~laosEventArgs~8);
135             ~returnValue~2 = (bool) ~laosEventArgs~8.ReturnValue;
136         }
137         catch (Exception ~exception~6)
138         {
139             ~laosEventArgs~8.Exception = ~exception~6;
140             ~PostSharp~Laos~Implementation.~aspect~2.OnException(~laosEventArgs~8);
141             switch (~laosEventArgs~8.FlowBehavior)
142             {
143                 case FlowBehavior.Continue:
144                     return ~returnValue~2;
145
146                 case FlowBehavior.Return:
147                     return (bool) ~laosEventArgs~8.ReturnValue;
148             }
149             throw;
150         }
151         finally
152         {
153             ~laosEventArgs~8.ReturnValue = ~returnValue~2;
154             ~PostSharp~Laos~Implementation.~aspect~2.OnExit(~laosEventArgs~8);
155             ~returnValue~2 = (bool) ~laosEventArgs~8.ReturnValue;
156         }
157         return ~returnValue~2;
158     }
159 }

這裡可以看出,如果是在AOP的異常捕獲裡面標記 eventArgs.FlowBehavior = FlowBehavior.Return,那麼標記的方法將不會執行。

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