目 录
准备工作完成后,DynamicProxy类就可以开始了。
创建代理对象 Create
创建代理对象主要分为五步:
(1)、获取被代理类型构造函数参数列表
Type[] parameterTypes = parameters == null ? Type.EmptyTypes : parameters.Select(p => p.GetType()).ToArray(); (2)、根据构造函数参数列表创建代理类型
Type proxyType = CreateProxyType(srcType, parameterTypes); (3)、使用动态方法生成创建代理类型实例的委托
CreateFunc(proxyType, parameterTypes) (4)、生成ProxyType对象,存入代理类型字典,以备二次调用
obj = new ProxyType(srcType.FullName, signature, CreateFunc (proxyType, parameterTypes)); func_Dictionary.Add(srcType.FullName + "(" + signature + ")", obj); (5)、通过委托生成代理对象
Func
1 ///2 /// 创建代理类型 3 /// 4 /// 类型 5 /// 参数 6 ///7 private static Type CreateProxyType(Type srcType, Type[] parameterTypes) 8 { 9 XNet.XCore.XDynamic.BuilderCollection bc = new XDynamic.BuilderCollection10 (srcType.Name + "_Aop_Assmely", srcType.Name + "_Aop_Module", srcType.Name + "_Proxy", srcType, parameterTypes);11 12 13 foreach (var propertyInfo in srcType.GetProperties())14 OverrideProperty(bc.DynamicTypeBuilder, propertyInfo);15 16 //切入方法17 MethodInfo[] methods = srcType.GetMethods(BindingFlags.Public | BindingFlags.Instance);18 19 for (int i = 0; i < methods.Length; i++)20 {21 var method = methods[i];22 23 if (!method.IsPublic || !method.IsVirtual || XDynamic.IsObjectMethod(method)) continue;24 25 object[] aspectAttributes = method.GetCustomAttributes(typeof(AspectAttribute), false);26 27 OverrideMethod(bc.DynamicTypeBuilder, method, aspectAttributes);28 }29 30 Type result = bc.DynamicTypeBuilder.CreateType();31 32 bc.DynamicAssemblyBuilder.Save(bc.AssemblyName.Name + ".dll");33 34 return result;35 }
1.1、根据构造函数参数列表创建代理类型 CreateProxyType
(1)、通过Emit生成动态程序集、动态模块以及动态类型
XNet.XCore.XDynamic.BuilderCollection bc = new XDynamic.BuilderCollection
(srcType.Name + "_Aop_Assmely", srcType.Name + "_Aop_Module", srcType.Name + "_Proxy", srcType, parameterTypes);(2)、重写被切入的属性
OverrideProperty(bc.DynamicTypeBuilder, propertyInfo);
(3)、重写被切入的方法
OverrideMethod(bc.DynamicTypeBuilder, method, aspectAttributes);
(4)、生成代理类型
Type result = bc.DynamicTypeBuilder.CreateType();
1 ///2 /// 创建代理类型 3 /// 4 /// 类型 5 /// 参数 6 ///7 private static Type CreateProxyType(Type srcType, Type[] parameterTypes) 8 { 9 XNet.XCore.XDynamic.BuilderCollection bc = new XDynamic.BuilderCollection10 (srcType.Name + "_Aop_Assmely", srcType.Name + "_Aop_Module", srcType.Name + "_Proxy", srcType, parameterTypes);11 12 13 foreach (var propertyInfo in srcType.GetProperties())14 OverrideProperty(bc.DynamicTypeBuilder, propertyInfo);15 16 //切入方法17 MethodInfo[] methods = srcType.GetMethods(BindingFlags.Public | BindingFlags.Instance);18 19 for (int i = 0; i < methods.Length; i++)20 {21 var method = methods[i];22 23 if (!method.IsPublic || !method.IsVirtual || XDynamic.IsObjectMethod(method)) continue;24 25 object[] aspectAttributes = method.GetCustomAttributes(typeof(AspectAttribute), false);26 27 OverrideMethod(bc.DynamicTypeBuilder, method, aspectAttributes);28 }29 30 Type result = bc.DynamicTypeBuilder.CreateType();31 32 bc.DynamicAssemblyBuilder.Save(bc.AssemblyName.Name + ".dll");33 34 return result;35 }
1.1.1 重写被切入的属性 OverrideProperty
1 ///2 /// 重写被代理类的属性 3 /// 4 /// 5 /// 属性信息 6 /// 切面范围 7 /// 切面公共调用方法 8 private static void OverrideProperty(TypeBuilder dynamicTypeBuilder, PropertyInfo info) 9 {10 //不需要切入直接返回11 object[] aspectAttributes = info.GetCustomAttributes(typeof(AspectAttribute), false);12 13 if (aspectAttributes.Length == 0) return;14 15 PropertyBuilder dynamicPropertyBuilder = dynamicTypeBuilder.DefineProperty(info.Name, PropertyAttributes.HasDefault, info.PropertyType, null);16 17 //Getter Setter 方法标识18 MethodAttributes getSetAttr = MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig | MethodAttributes.Virtual;19 20 MethodBuilder getter = dynamicTypeBuilder.DefineMethod("get_" + info.Name, getSetAttr, info.PropertyType, Type.EmptyTypes);21 22 ILGenerator getIL = getter.GetILGenerator();23 24 ILGenerateProxyMethod(getIL, info.GetGetMethod(), Type.EmptyTypes, aspectAttributes);25 26 27 //覆盖自动生成的Getter28 MethodInfo getMethod = info.GetGetMethod();29 30 if (getMethod != null) dynamicTypeBuilder.DefineMethodOverride(getter, getMethod);31 32 //给属性设置Get、Set方法33 dynamicPropertyBuilder.SetGetMethod(getter);34 35 36 //重写Set 方法37 MethodBuilder setter = dynamicTypeBuilder.DefineMethod("set_" + info.Name, getSetAttr, typeof(void), new Type[] { info.PropertyType });38 39 ILGenerator setIL = setter.GetILGenerator();40 41 ILGenerateProxyMethod(setIL, info.GetSetMethod(), new Type[] { info.PropertyType }, aspectAttributes);42 43 44 //覆盖自动生成的Setter45 MethodInfo setMethod = info.GetSetMethod();46 47 if (setMethod != null) dynamicTypeBuilder.DefineMethodOverride(setter, setMethod);48 49 dynamicPropertyBuilder.SetSetMethod(setter);50 }
1.1.2 重写被切入的方法 OverrideMethod
1 ///2 /// 重写被代理类的指定方法 3 /// 4 /// 类型 5 /// 被代理方法 6 /// 代理特性集合 7 private static void OverrideMethod(TypeBuilder typeBuilder, MethodInfo src_Method, object[] aspectAttributes) 8 { 9 if (aspectAttributes == null || aspectAttributes.Length == 0) return;10 11 MethodAttributes attr = MethodAttributes.Public | MethodAttributes.Family | MethodAttributes.HideBySig | MethodAttributes.Virtual;12 13 //获取当前方法参数列表14 Type[] paramTypes = XDynamic.GetMethodParameterTypes(src_Method);15 16 ILGenerator il = typeBuilder.DefineMethod(src_Method.Name, attr, src_Method.ReturnType, paramTypes).GetILGenerator();17 18 ILGenerateProxyMethod(il, src_Method, paramTypes, aspectAttributes);19 }
1.1.3 生成代理方法 ILGenerateProxyMethod
1 ///2 /// 3 /// 4 /// 5 /// 6 /// 7 /// 8 private static void ILGenerateProxyMethod(ILGenerator il_ProxyMethod, MethodInfo src_Method, Type[] paramTypes, object[] aspectAttributes) 9 {10 int aspectCount = aspectAttributes.Length;11 12 //生成切面上下文13 LocalBuilder aspectContext = CreateAspectContext(il_ProxyMethod, src_Method.Name, paramTypes);14 15 //申明临时存放切面对象和OnExit方法的变量16 var aspectLocalBuilders = new LocalBuilder[aspectCount];17 var onExit_Methods = new MethodInfo[aspectCount];18 19 20 //初始化标记的切面对象,并调用切面对象的OnEntry方法21 for (int i = 0; i < aspectCount; i++)22 {23 //创建一个切面对象24 var aspectType = aspectAttributes[i].GetType();25 var aspect = il_ProxyMethod.DeclareLocal(aspectType);26 ConstructorInfo constructor = aspectType.GetConstructor(Type.EmptyTypes);27 28 il_ProxyMethod.Emit(OpCodes.Newobj, constructor);29 il_ProxyMethod.Emit(OpCodes.Stloc, aspect);30 31 var onEntry_method = aspectType.GetMethod("OnEntry");32 onExit_Methods[i] = aspectType.GetMethod("OnExit");33 34 //调用BeforeInvoke35 il_ProxyMethod.Emit(OpCodes.Ldloc, aspect);36 il_ProxyMethod.Emit(OpCodes.Ldloc, aspectContext);37 il_ProxyMethod.Emit(OpCodes.Callvirt, onEntry_method);38 il_ProxyMethod.Emit(OpCodes.Nop);39 40 aspectLocalBuilders[i] = aspect;41 }42 43 //类对象,参数值依次入栈44 for (int i = 0; i <= paramTypes.Length; i++)45 il_ProxyMethod.Emit(OpCodes.Ldarg, i);46 47 //调用基类的方法48 il_ProxyMethod.Emit(OpCodes.Call, src_Method);49 50 51 //定义返回值52 LocalBuilder result = null;53 54 //如果有返回值,保存返回值到局部变量55 if (src_Method.ReturnType != typeof(void))56 {57 result = il_ProxyMethod.DeclareLocal(src_Method.ReturnType);58 il_ProxyMethod.Emit(OpCodes.Stloc, result);59 60 //给AspectContext的属性Result赋值61 var resultSetMethod = typeof(AspectContext).GetMethod("set_Result");62 il_ProxyMethod.Emit(OpCodes.Ldloc, aspectContext); //加载AspectContext局部变量63 il_ProxyMethod.Emit(OpCodes.Ldloc, result);//加载返回值64 il_ProxyMethod.Emit(OpCodes.Box, src_Method.ReturnType);65 il_ProxyMethod.Emit(OpCodes.Call, resultSetMethod);//赋值66 }67 68 //调用横切对象的OnExit方法69 for (int i = 0; i < aspectCount; i++)70 {71 il_ProxyMethod.Emit(OpCodes.Ldloc, aspectLocalBuilders[i]);72 il_ProxyMethod.Emit(OpCodes.Ldloc, aspectContext);73 il_ProxyMethod.Emit(OpCodes.Callvirt, onExit_Methods[i]);74 il_ProxyMethod.Emit(OpCodes.Nop);75 }76 77 //如果有返回值,则把返回值压栈78 if (result != null)79 il_ProxyMethod.Emit(OpCodes.Ldloc, result);80 81 il_ProxyMethod.Emit(OpCodes.Ret);//返回82 }
1.1.4 生成切面上下文对象 CreateAspectContext
1 ///2 /// 生成切面上下文对象 3 /// 4 /// 5 /// 方法名称 6 /// 参数类型 7 ///8 private static LocalBuilder CreateAspectContext(ILGenerator il, string methodName, Type[] paramTypes) 9 {10 //AspectContext.ParameterArgs 类型为 object[]11 12 //声明一个类型为object的局部数组13 il.DeclareLocal(typeof(object[]));14 //数组长度入栈15 il.Emit(OpCodes.Ldc_I4, paramTypes.Length);16 //生成新数组17 il.Emit(OpCodes.Newarr, typeof(object));18 //赋值给局部数组变量19 il.Emit(OpCodes.Stloc_0);20 21 //遍历参数,并存入数组22 for (int i = 0; i < paramTypes.Length; i++)23 {24 il.Emit(OpCodes.Ldloc_0);//数组入栈25 il.Emit(OpCodes.Ldc_I4, i);//数组下标入栈26 il.Emit(OpCodes.Ldarg, i + 1);//按下标加载对应的参数27 if (paramTypes[i].IsValueType)//参数为值类型,装箱28 il.Emit(OpCodes.Box, paramTypes[i]);29 il.Emit(OpCodes.Stelem_Ref);//将参数存入数组30 }31 32 //获取AspectContext构造函数33 Type aspectContextType = typeof(AspectContext);34 ConstructorInfo info = aspectContextType.GetConstructor(new Type[] { typeof(object), typeof(string), typeof(object[]) });35 36 //生成一个AspectContext 对象37 il.Emit(OpCodes.Ldarg_0);//加载调用对象38 il.Emit(OpCodes.Ldstr, methodName);//加载方法名称39 il.Emit(OpCodes.Ldloc_0);//加载由参数生成的局部数组变量40 il.Emit(OpCodes.Newobj, info);41 42 //声明一个AspectContext局部变量43 LocalBuilder aspectContext = il.DeclareLocal(aspectContextType);44 il.Emit(OpCodes.Stloc, aspectContext);45 46 return aspectContext;47 }
1.2 使用动态方法生成创建代理类型实例的委托
1 ///2 /// 生成创建代理类型实例的委托 3 /// 4 ///被代理类型 5 /// 代理类型 6 /// 代理类型构造函数参数类型 7 ///8 private static Func
1.3 ProxyType类
1 public class ProxyType2 { 3 #region 构造函数 4 /// 5 /// 构造函数 6 /// 7 /// 类型名称 8 /// 构造函数参数签名 9 /// 创建被代理类型实例的委托10 public ProxyType(string name, string parameterSignature, FunccreateFunc)11 {12 Name = name; ParameterSignature = parameterSignature; CreateFunc = createFunc;13 }14 #endregion15 16 #region 属性17 18 /// 19 /// 名称20 /// 21 public string Name { get; set; }22 23 ///24 /// 参数类型签名25 /// 26 public string ParameterSignature { get; set; }27 28 ///29 /// 创建被代理类型实例的委托30 /// 31 public FuncCreateFunc { get; set; }32 33 #endregion34 }
到此为止一个简单的Aop框架就完成了。下一篇会介绍一个下BuilderCollection类