利用.NET Core类库System.Reflection.DispatchProxy实现简易Aop
背景
Aop即是面向切面编程,众多Aop框架里Castle是最为人所知的,另外还有死去的Spring.NET,当然,.NET Core社区新秀AspectCore在性能与功能上都非常优秀,已经逐渐被社区推崇和有越来越多的人使用。感谢柠檬同学的礼物!
如果大家出于自身需求或者学习,想实现一个Aop,是不是觉得一来就要使用Emit去做?最近我了解到了System.Reflection.DispatchProxy这个corefx类库,已经实现了动态代理功能。
System.Reflection.DispatchProxy
下面演示一下它的使用方法:
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;
}
}
改造成一款简易AOP
为什么?
System.Reflection.DispatchProxy只有一个Api,就是objecct Create<T,TProxy>() where TProxy:DispatchProxy,约束了只能传入泛型参数,并不能从方法传入类型,这就会带来很多问题。而更可气的是,给官方提了issue之后,还是不给增加这个api……
改造方法
幸好,在那个issue下,issue作者提供了一个解决方案,就是用反射来构造这个泛型方法。我还在这基础上,封装了一下,加入了传入拦截器实例和传入拦截器构造方法参数的功能。
/// <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的封装,实现更多创建代理实例的方法
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);
}
}
使用方法
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);
}
总结
总结一下就是,微软爸爸给我们的这个轮子还是即轻便又很好用的。
本文的实例代码可以在我的github上找到:https://github.com/ElderJames/CoreProxy
利用.NET Core类库System.Reflection.DispatchProxy实现简易Aop的更多相关文章
- 利用system.reflection遍历一个类的变量成员
假设有下面一个类,在程序中已初始化,如何获取里面的变量成员name,age,onduty及其值呢? public class Employee { public string name; public ...
- 使用.net core中的类DispatchProxy实现AOP
在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术.AOP是软件开发中的一个热点,利用A ...
- Asp.net core下利用EF core实现从数据实现多租户(1)
前言 随着互联网的的高速发展,大多数的公司由于一开始使用的传统的硬件/软件架构,导致在业务不断发展的同时,系统也逐渐地逼近传统结构的极限. 于是,系统也急需进行结构上的升级换代. 在服务端,系统的I/ ...
- System.Reflection 获取描述
我们需要获取类,属性,方法的描述.这个跟获取枚举的描述一样,需要我们通过反射来做.这还需要我们的利用System.ComponentModel:Description 的属性来完成. 新建一个类:使 ...
- C#反射实例(一) 利用反射使用类库
在网上查找了不少的资料,可以说大同小异,概念性的东西网上一搜一堆,今天把反射的东西整理了一下,供大家使用,我保证我这里是最全面的东西,当然也是基础的东西,在学好了这一切的基础上,大家可以学习反射的具体 ...
- 如何将一个.NET Core类库发布到NuGet
包治百病 | 如何将一个.NET Core类库发布到NuGet 写文章 包治百病 | 如何将一个.NET Core类库发布到NuGet Edi Wang发表于汪宇杰博客订阅 77 NuGet是.NET ...
- Asp.net core下利用EF core实现从数据实现多租户(3): 按Schema分离 附加:EF Migration 操作
前言 前段时间写了EF core实现多租户的文章,实现了根据数据库,数据表进行多租户数据隔离. 今天开始写按照Schema分离的文章. 其实还有一种,是通过在数据表内添加一个字段做多租户的,但是这种模 ...
- 【asp.net core 系列】8 实战之 利用 EF Core 完成数据操作层的实现
0. 前言 通过前两篇,我们创建了一个项目,并规定了一个基本的数据层访问接口.这一篇,我们将以EF Core为例演示一下数据层访问接口如何实现,以及实现中需要注意的地方. 1. 添加EF Core 先 ...
- Could not load type 'System.Reflection.AssemblySignatureKeyAttribute' from assembly 'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c
错误: Could not load type 'System.Reflection.AssemblySignatureKeyAttribute' from assembly 'mscorlib, V ...
随机推荐
- ACM练习网站
1.http://www.acmerblog.com/ Acm之家 2.http://acm.nyist.net/JudgeOnline/problemset.php 南阳理工学院
- IDEA Maven Mybatis generator 自动生成代码
IDEA Maven Mybatis generator 自动生成代码 一.安装配置maven以及在Idea中配置maven 安装过程步骤可以看上面的博文,里面介绍得很详细. 二.建数据表 DROP ...
- Kibana插件sentinl实现邮件报警
为什么会突然想用到对日志的异常内容进行邮件报警,是因为在上周公司的线上业务多次出现锁表,开发在优化sql的同时,我也在想是不是可以对日志的异常内容进行检测并实现邮件预警. 在网上查询了一些资料后,决定 ...
- poj 1222EXTENDED LIGHTS OUT
高斯消元的题本质思想一样. 学习网址:http://www.cnblogs.com/rainydays/archive/2011/08/31/2160748.html #include <ios ...
- 陈新宇:CKafka在人脸识别PAAS中的应用
欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文首发在云+社区,未经许可,不得转载. 我叫陈新宇,在格灵深瞳负责数据流的研发,首先特别感谢如今老师,他们把Kafka一个优秀的消息中间件 ...
- vue2.0读书笔记2-进阶
一.深入响应式原理 二.过渡效果 三.过渡状态 四.Render函数 五.自定义指令 六.混合 七.插件 八.单文件组件 九.生产环境 十.路由 vue-router: http://router.v ...
- Datenstruktur und Algorithmus
In der Informatik und Softwaretechnik ist eine Datenstruktur ein Objekt zur Speicherung und Organisa ...
- IOS学习资源汇总
昨天夜里在简书看到关于ios学习资源总结的文章,在这分享给大家. http://www.jianshu.com/p/b7c4a787a597?utm_campaign=hugo&utm_med ...
- C# XML创建解析、XML格式化
导入命名空间: VS需要在项目中添加引用system.XML; 代码中添加 using System.XML和using System.IO; XML范例: <?xml version=&quo ...
- Skype坑爹报错:“旧版本无法删除,请联络您的技术支持小组 ”的解决办法
真是恶心的让人想吐的报错.现在终于解决了,跟大家分享一下方法. 先给问题截个图,如下 首先当我去搜解决办法之前,我已经在[控制面板]的[卸载程序]里把Skype删除了,真是让我后悔不已的操作啊!!因为 ...