当前位置: 移动技术网 > IT编程>开发语言>.net > .NET Core类库System.Reflection.DispatchProxy实现简易Aop的方法

.NET Core类库System.Reflection.DispatchProxy实现简易Aop的方法

2019年01月07日  | 移动技术网IT编程  | 我要评论

广州性,山西万荣第二小学事件,大城小事 小品

前言

aop即是面向切面编程,众多aop框架里castle是最为人所知的,另外还有死去的spring.net,当然,.net core社区新秀aspectcore在性能与功能上都非常优秀,已经逐渐被社区推崇和有越来越多的人使用。感谢柠檬同学的礼物!

如果大家出于自身需求或者学习,想实现一个aop,是不是觉得一来就要使用emit去做?最近我了解到了system.reflection.dispatchproxy这个corefx类库,已经实现了动态代理功能。

1|1system.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;
 }
}

2|0改造成一款简易aop

2|1为什么?

system.reflection.dispatchproxy只有一个api,就是objecct create<t,tproxy>() where tproxy:dispatchproxy,约束了只能传入泛型参数,并不能从方法传入类型,这就会带来很多问题。而更可气的是,给官方提了issue之后,还是不给增加这个api……

2|2改造方法

幸好,在那个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);
 }
}

2|3使用方法

 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

好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对移动技术网的支持。

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网