前言
aop即是面向切面編程,眾多Aop框架里Castle是最為人所知的,另外還有死去的Spring.NET,當然,.NET Core社區新秀AspectCore在性能與功能上都非常優秀,已經逐漸被社區推崇和有越來越多的人使用。感謝檸檬同學的禮物!
如果大家出于自身需求或者學習,想實現一個Aop,是不是覺得一來就要使用Emit去做?最近我了解到了System.Reflection.DispatchProxy這個corefx類庫,已經實現了動態代理功能。
1|1System.Reflection.DispatchProxy
下面演示一下它的使用方法:
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
|
class Program { static void Main( string [] args) { //創建代理類,并把SampleProxy作為攔截器注入 var sampleProxy = (targetInterface)SampleProxy.Create<targetInterface, SampleProxy>(); //執行接口方法 sampleProxy.Write( "here is invoke by proxy" ); } } //需要被生成代理實例的接口 public interface targetInterface { //這個方法會被代理類實現 void Write( string writesomeshing); } public class SampleProxy : DispatchProxy { /// <summary> /// 攔截調用 /// </summary> /// <param name="method">所攔截的方法信息</param> /// <param name="parameters">所攔截方法被傳入的參數指</param> /// <returns></returns> protected override object Invoke(MethodInfo targetMethod, object [] args) { Console.WriteLine(args[0]); return null ; } } |
2|0改造成一款簡易AOP
2|1為什么?
System.Reflection.DispatchProxy只有一個Api,就是objecct Create<T,TProxy>() where TProxy:DispatchProxy,約束了只能傳入泛型參數,并不能從方法傳入類型,這就會帶來很多問題。而更可氣的是,給官方提了issue之后,還是不給增加這個api……
2|2改造方法
幸好,在那個issue下,issue作者提供了一個解決方案,就是用反射來構造這個泛型方法。我還在這基礎上,封裝了一下,加入了傳入攔截器實例和傳入攔截器構造方法參數的功能。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
/// <summary> /// 攔截器接口 /// </summary> public interface IInterceptor { /// <summary> /// 攔截器調用 /// </summary> /// <param name="target">代理實例</param> /// <param name="method">所攔截的方法</param> /// <param name="parameters">所攔截方法傳入的參數值</param> /// <returns>返回值會傳遞給方法返回值</returns> object Intercept( object target, MethodInfo method, object [] parameters); } |
攔截器要實現這個接口,下面是對DispatchProxy的封裝,實現更多創建代理實例的方法
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
|
public class ProxyGenerator : DispatchProxy { private IInterceptor interceptor { get ; set ; } /// <summary> /// 創建代理實例 /// </summary> /// <param name="targetType">所要代理的接口類型</param> /// <param name="interceptor">攔截器</param> /// <returns>代理實例</returns> public static object Create(Type targetType, IInterceptor interceptor) { object proxy = GetProxy(targetType); ((ProxyGenerator)proxy).CreateInstance(interceptor); return proxy; } /// <summary> /// 創建代理實例 /// </summary> /// <param name="targetType">所要代理的接口類型</param> /// <param name="interceptorType">攔截器類型</param> /// <param name="parameters">攔截器構造函數參數值</param> /// <returns>代理實例</returns> public static object Create(Type targetType, Type interceptorType, params object [] parameters) { object proxy = GetProxy(targetType); ((ProxyGenerator)proxy).CreateInstance(interceptorType, parameters); return proxy; } /// <summary> /// 創建代理實例 TTarget:所要代理的接口類型 TInterceptor:攔截器類型 /// </summary> /// <param name="parameters">攔截器構造函數參數值</param> /// <returns>代理實例</returns> public static TTarget Create<TTarget, TInterceptor>( params object [] parameters) where TInterceptor : IInterceptor { var proxy = GetProxy( typeof (TTarget)); ((ProxyGenerator)proxy).CreateInstance( typeof (TInterceptor), parameters); return (TTarget)proxy; } private static object GetProxy(Type targetType) { var callexp = Expression.Call( typeof (DispatchProxy), nameof(DispatchProxy.Create), new [] { targetType, typeof (ProxyGenerator) }); return Expression.Lambda<Func< object >>(callexp).Compile()(); } private void CreateInstance(Type interceptorType, object [] parameters) { var ctorParams = parameters.Select(x => x.GetType()).ToArray(); var paramsExp = parameters.Select(x => Expression.Constant(x)); var newExp = Expression.New(interceptorType.GetConstructor(ctorParams), paramsExp); this .interceptor = Expression.Lambda<Func<IInterceptor>>(newExp).Compile()(); } private void CreateInstance(IInterceptor interceptor) { this .interceptor = interceptor; } protected override object Invoke(MethodInfo method, object [] parameters) { return this .interceptor.Intercept(method, parameters); } } |
2|3使用方法
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
|
class Program { static void Main( string [] args) { var poxy1 = (targetInterface)ProxyGenerator.Create( typeof (targetInterface), new SampleProxy( "coreproxy1" )); poxy1.Write( "here was invoked" ); //---> "here was invoked by coreproxy1" var poxy2 = (targetInterface)ProxyGenerator.Create( typeof (targetInterface), typeof (SampleProxy), "coreproxy2" ); poxy2.Write( "here was invoked" ); //---> "here was invoked by coreproxy2" var poxy3 = ProxyGenerator.Create<targetInterface, SampleProxy>( "coreproxy3" ); poxy3.Write( "here was invoked" ); //---> "here was invoked by coreproxy3" } } public class SampleProxy : IInterceptor { private string proxyName { get ; } public SampleProxy( string name) { this .proxyName = name; } public object Intercept(MethodInfo method, object [] parameters) { Console.WriteLine(parameters[0] + " by " + proxyName); return null ; } } public interface targetInterface { void Write( string writesome); } |
3|0總結
總結一下就是,微軟爸爸給我們的這個輪子還是即輕便又很好用的。
本文的實例代碼可以在我的github上找到:https://github.com/ElderJames/CoreProxy
好了,以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對服務器之家的支持。
原文鏈接:https://www.cnblogs.com/ElderJames/p/implement-simple-Aop-using-a-dotnet-core-library-System-Reflection-DispatchProxy.html