前言
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