前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Aop动态生成代理类时支持带参数构造函数

Aop动态生成代理类时支持带参数构造函数

作者头像
Zachary_ZF
发布2018-09-10 15:18:07
1.1K0
发布2018-09-10 15:18:07
举报
文章被收录于专栏:跨界架构师跨界架构师

一、背景

  在某些情况下,我们需要植入AOP代码的类并没有默认构造函数。那么此时动态生成的代理类也需要相同签名的构造函数,并且内部调用原始类的构造函数。自己折腾了1晚上没搞定,现在搞定了发出来供大家一起学习探讨。

二、梳理功能点

  在已支持通过默认构造函数进行AOP代码植入的情况下(以前发过一篇博文,传送门:大家一起Aop),实现该功能我们需要做的是:

  1.如何通过获取原始类的构造函数参数列表,并使用Emit生成代理类的相应构造函数。

  2.如何创建并保存实例化代理类的委托,加快实例化速度。

三、实现方案

  功能1:

  在原来的生成代理类,代理类中的方法处增加生成构造函数的代码。代码很简单,如下:  

代码语言:javascript
复制
 1             if (_parameters == null || _parameters.Length == 0)
 2             {
 3                 return typeBuilder;
 4             }
 5 
 6             var baseConstructor = _originalType.GetConstructor(_parameterTypes);
 7             if (baseConstructor == null)
 8                 throw new MissingMethodException("未找到相应参数的构造函数");
 9 
10             const MethodAttributes METHOD_ATTRIBUTES = MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName | MethodAttributes.Public;
11             var constructor = typeBuilder.DefineConstructor(METHOD_ATTRIBUTES, CallingConventions.HasThis, _parameterTypes);
12 
13             var il = constructor.GetILGenerator();
14 
15             il.Emit(OpCodes.Ldarg_0);
16 
17             for (int i = 1; i <= _parameters.Length; i++)  //这里要注意下,索引为0的参数是当前对象本身
18             {
19                 il.Emit(OpCodes.Ldarg, i);
20             }
21 
22             il.Emit(OpCodes.Call, baseConstructor);
23             il.Emit(OpCodes.Ret);
24 
25             return typeBuilder;

  其中要注意2点,

  ①定义构造函数的时候需要指定MethodAttributes,平常我们代码编写的公有构造函数就是上面写的4个。

  ②因为我们定义的是构造函数,所以此处必须指定CallingConventions.HasThis。至于为什么去看msdn的解释,不在我们本次讨论范围内。

  到这里我们的动态类的构造已经完成了,接下去解决功能2:

  这里只要在原先直接取默认构造函数的地方增加一个判断,获取指定参数的构造函数来构造委托。下面贴代码:

代码语言:javascript
复制
 1         private DynamicMethod GetConstructorMethod<TReturnType>(Type aopType)
 2         {
 3             var method = _parameters == null || _parameters.Length == 0
 4                         ? new DynamicMethod("", typeof(TReturnType), null)
 5                         : new DynamicMethod("", typeof(TReturnType), _parameterTypes);
 6 
 7             var il = method.GetILGenerator();
 8 
 9             BuildConstructorIl(il, aopType);
10 
11             return method;
12         }
13  
14  
15          private void BuildConstructorIl(ILGenerator il, Type aopType)
16          {
17              if (_parameters == null || _parameters.Length == 0)
18              {
19                  ConstructorInfo info = aopType.GetConstructor(Type.EmptyTypes);
20                  if (info == null)
21                      return;
22  
23                  il.Emit(OpCodes.Newobj, info);
24                  il.Emit(OpCodes.Ret);
25              }
26              else
27              {
28                  ConstructorInfo info = aopType.GetConstructor(_parameterTypes);
29                  if (info == null)
30                      return;
31  
32                  var localInstance = il.DeclareLocal(aopType);
33                  for (int i = 0; i < _parameterTypes.Length; i++) //这里与上面的标红不同,这里因为是直接定义了一个方法,并且不存在实例,所以此处参数从索引0开始
34                      il.Emit(OpCodes.Ldarg, i);
35  
36                  il.Emit(OpCodes.Newobj, info);
37  
38                  il.Emit(OpCodes.Stloc, localInstance);
39                  il.Emit(OpCodes.Ldloc, localInstance);
40                  il.Emit(OpCodes.Ret);
41              }
42          }

  这里需要的注意的点已经标红出来了。但这里仅是核心代码,在外层再封装几个重载用于生成不同的Func<>。

代码语言:javascript
复制
 1         public Func<TReturnType> CreateFunc<TReturnType>(Type aopType)
 2         {
 3             var method = GetConstructorMethod<TReturnType>(aopType);
 4 
 5             return method.CreateDelegate(typeof(Func<TReturnType>)) as Func<TReturnType>;
 6         }
 7 
 8         public Func<TP1, TReturnType> CreateFunc<TP1, TReturnType>(Type aopType)
 9         {
10             var method = GetConstructorMethod<TReturnType>(aopType);
11 
12             return method.CreateDelegate(typeof(Func<TP1, TReturnType>)) as Func<TP1, TReturnType>;
13         }
14 
15         public Func<TP1, TP2, TReturnType> CreateFunc<TP1, TP2, TReturnType>(Type aopType)
16         {
17             var method = GetConstructorMethod<TReturnType>(aopType);
18 
19             return method.CreateDelegate(typeof(Func<TP1, TP2, TReturnType>)) as Func<TP1, TP2, TReturnType>;
20         }

大功告成~,再进行一些简单的重构。测试效果:

四、收尾

  源码附上:源码+Demo在此!

  觉得有用记得点赞哦~

作者: Zachary_Fan 出处:http://www.cnblogs.com/Zachary-Fan/p/5629992.html

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2016-06-30 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档