/// <summary> /// 生成代理类型 /// </summary> /// <param name="interfaceType">实现的接口或继承</param> /// <param name="implementationType">实现的类型</param> /// <param name="Inherit">是否通过继承生成</param> /// <returns></returns> public static Type CreateProxyClassType(Type interfaceType, Type implementationType, bool Inherit = false) { // ASP.NET Core 中,可能只有接口 if (implementationType == null) { return(null); } Type type = implementationType; if (implementationType.GetCustomAttribute(typeof(InterceptorAttribute)) == null) { return(type); } TypeBuilder typeBuilder; if (Inherit) { if (CacheProxyClass.ContainsKey(implementationType)) { return(CacheProxyClass[type]); } typeBuilder = moduleBuilder.DefineType("CZGLAOP." + type.Name + _TypeName, type.Attributes, type); } else { if (CacheProxyClass.ContainsKey(implementationType)) { return(CacheProxyClass[interfaceType]); } typeBuilder = moduleBuilder.DefineType("CZGLAOP." + type.Name + _TypeName, type.Attributes, type); } // 判断是否为泛型,如果是则构造其为泛型 bool isGeneric = EmitHelper.DefineGenericParameters(typeBuilder, type); // 生成代理类型 Type proxyType = ActionInterceptor(type, typeBuilder, Inherit); CacheProxyClass.TryAdd(implementationType, proxyType); return(proxyType); }
/// <summary> /// 通过非侵入式来生成代理类型 /// </summary> /// <param name="interfaceType">实现的接口或继承</param> /// <param name="implementationType">实现的类型</param> /// <param name="Inherit">是否通过继承生成</param> /// <returns></returns> public static Type CreateProxyClassTypeNoAttribute(Type implementationType, NoActionAttributeModel noAction) { Type type = implementationType; TypeBuilder typeBuilder; if (CacheProxyClass.ContainsKey(implementationType)) { return(CacheProxyClass[type]); } typeBuilder = moduleBuilder.DefineType("CZGLAOP." + type.Name + _TypeName, type.Attributes, type); // 判断是否为泛型,如果是则构造其为泛型 bool isGeneric = EmitHelper.DefineGenericParameters(typeBuilder, type); // 生成代理类型 Type proxyType = ActionInterceptor(type, typeBuilder, true, noAction); CacheProxyClass.TryAdd(implementationType, proxyType); return(proxyType); }
/// <summary> /// 生成属性的代理方法 /// </summary> /// <param name="iL">IL生成器</param> /// <param name="type">被代理的类</param> /// <param name="methodInfo">被代理的方法,Get或Set方法</param> /// <param name="propertyInfo">当前被代理的属性</param> /// <param name="aspectContextField">类的上下文</param> /// <param name="fieldBuilder">使用的拦截器字段</param> /// <param name="actionAttr">使用的拦截器</param> public static void PropertyProxy(ILGenerator iL, Type type, MethodInfo methodInfo, PropertyInfo propertyInfo, FieldBuilder aspectContextField, FieldBuilder fieldBuilder, ActionAttribute actionAttr) { Type returnType = methodInfo.ReturnType; // 返回类型 bool isSet = returnType == typeof(void) ? true : false; Type paramTypes = methodInfo.GetParameters().Select(x => x.ParameterType).FirstOrDefault(); // 参数列表 // 五个步骤: // * 为上下文设置参数 // * 执行 拦截器的 Before() // * 执行被代理了类的方法 // * 执行拦截器的 After() // * 返回值(如果有) // 预先定义部分变量 LocalBuilder tmpAspectContextBodyField = iL.DeclareLocal(typeof(AspectContextBody)); // 上下文实例,堆栈在 Stloc_0 if (returnType != typeof(void)) // 如果有返回值时 { iL.DeclareLocal(returnType); // 用于接收返回结果,堆栈在 Stloc_1 } // 创建一个新的上下文 iL.Emit(OpCodes.Ldarg_0); iL.Emit(OpCodes.Ldfld, aspectContextField); iL.Emit(OpCodes.Callvirt, typeof(AspectContextBody).GetMethod($"get_{nameof(AspectContextBody.NewInstance)}")); iL.Emit(OpCodes.Stloc_0); // 存到堆栈 0 // ① // IsProperty = true iL.Emit(OpCodes.Ldloc_0); iL.Emit(OpCodes.Ldc_I4_1); // 0 false 1 true iL.Emit(OpCodes.Callvirt, typeof(AspectContextBody).GetMethod($"set_{nameof(AspectContextBody.IsProperty)}")); // PropertyInfo iL.Emit(OpCodes.Ldloc_0); iL.Emit(OpCodes.Ldarg_0); iL.Emit(OpCodes.Call, typeof(object).GetMethod("GetType")); iL.Emit(OpCodes.Ldstr, propertyInfo.Name); iL.Emit(OpCodes.Call, typeof(Type).GetMethod(nameof(type.GetProperty), new Type[] { typeof(string) })); iL.Emit(OpCodes.Callvirt, typeof(AspectContextBody).GetMethod($"set_{nameof(AspectContextBody.PropertyInfo)}")); // PropertyValue // 如果是Set方法,那么在此处即可获得值 if (isSet) { iL.Emit(OpCodes.Ldloc_0); EmitHelper.EmitOne(iL, paramTypes); iL.Emit(OpCodes.Callvirt, typeof(AspectContextBody).GetMethod($"set_{nameof(AspectContextBody.PropertyValue)}")); } // ② 方法执行前 iL.Emit(OpCodes.Ldarg_0); iL.Emit(OpCodes.Ldfld, fieldBuilder); iL.Emit(OpCodes.Ldloc_0); iL.Emit(OpCodes.Callvirt, actionAttr.GetType().GetMethod(nameof(ActionAttribute.Before))); iL.Emit(OpCodes.Nop); // ③ 执行方法 if (isSet) { iL.Emit(OpCodes.Ldarg_0); iL.Emit(OpCodes.Ldloc_0); iL.Emit(OpCodes.Callvirt, typeof(AspectContextBody).GetMethod($"get_{nameof(AspectContextBody.PropertyValue)}")); if (returnType.IsValueType) { iL.Emit(OpCodes.Box, methodInfo.GetParameters().Select(x => x.ParameterType).First()); } else if (returnType != typeof(object)) { iL.Emit(OpCodes.Castclass, methodInfo.GetParameters().Select(x => x.ParameterType).First()); } } else { iL.Emit(OpCodes.Ldloc_0); iL.Emit(OpCodes.Ldarg_0); } iL.Emit(OpCodes.Call, methodInfo); // 有返回值时,使用上下文存储 if (returnType != typeof(void)) { // 值类型需要装箱 if (returnType.IsValueType) { iL.Emit(OpCodes.Box, returnType); } else if (returnType != typeof(object)) { iL.Emit(OpCodes.Castclass, returnType); } iL.Emit(OpCodes.Callvirt, typeof(AspectContextBody).GetMethod($"set_{nameof(AspectContextBody.PropertyValue)}")); } // ④ 执行方法后 iL.Emit(OpCodes.Ldarg_0); iL.Emit(OpCodes.Ldfld, fieldBuilder); iL.Emit(OpCodes.Ldloc_0); iL.Emit(OpCodes.Callvirt, actionAttr.GetType().GetMethod(nameof(ActionAttribute.After))); if (returnType != typeof(void)) { if (returnType.IsValueType) { iL.Emit(OpCodes.Unbox_Any, methodInfo.ReturnType); } else { iL.Emit(OpCodes.Castclass, methodInfo.ReturnType); } iL.Emit(OpCodes.Stloc_1); iL.Emit(OpCodes.Ldloc_1); // 取出堆栈中的返回值 } else { iL.Emit(OpCodes.Pop); } // ⑤ iL.Emit(OpCodes.Ret); }
/// <summary> /// 生成代理方法 /// </summary> /// <param name="iL">IL生成器</param> /// <param name="methodInfo">被代理的方法</param> /// <param name="aspectContextField">类的上下文</param> /// <param name="fieldBuilder">使用的拦截器字段</param> /// <param name="actionAttr">使用的拦截器</param> public static void MethodProxy(ILGenerator iL, MethodInfo methodInfo, FieldBuilder aspectContextField, FieldBuilder fieldBuilder, Type actionAttr) { Type returnType = methodInfo.ReturnType; // 返回类型 ParameterInfo[] types = methodInfo.GetParameters(); // 参数列表 // 五个步骤: // * 为上下文设置参数 // * 执行 拦截器的 Before() // * 执行被代理了类的方法 // * 执行拦截器的 After() // * 返回值(如果有) // 预先定义部分变量 LocalBuilder tmpAspectContextBodyField = iL.DeclareLocal(typeof(AspectContextBody)); // 上下文实例,堆栈在 Stloc_0 if (returnType != typeof(void)) // 如果有返回值时 { iL.DeclareLocal(returnType); // 用于接收返回结果,堆栈在 Stloc_1 } // 创建一个新的上下文 iL.Emit(OpCodes.Ldarg_0); // this iL.Emit(OpCodes.Ldfld, aspectContextField); // _AspectContextBody iL.Emit(OpCodes.Castclass, typeof(AspectContextBody)); iL.Emit(OpCodes.Callvirt, typeof(AspectContextBody).GetMethod($"get_{nameof(AspectContextBody.NewInstance)}")); // NewInstance iL.Emit(OpCodes.Stloc_0); // 调用 aspectContextBody 的 NewInstance 属性 // ① // IsMethod = true iL.Emit(OpCodes.Ldloc_0); // aspectContextBody iL.Emit(OpCodes.Ldc_I4_1); // 0 false 1 true iL.Emit(OpCodes.Callvirt, typeof(AspectContextBody).GetMethod($"set_{nameof(AspectContextBody.IsMethod)}")); // MethidInfo iL.Emit(OpCodes.Ldloc_0); iL.Emit(OpCodes.Call, typeof(MethodBase).GetMethod(nameof(MethodBase.GetCurrentMethod))); // 执行方法 iL.Emit(OpCodes.Castclass, typeof(MethodInfo)); // 尝试将引用传递的对象转换为指定的类。 iL.Emit(OpCodes.Callvirt, typeof(AspectContextBody).GetMethod($"set_{nameof(AspectContextBody.MethodInfo)}")); // MethodValues iL.Emit(OpCodes.Ldloc_0); EmitHelper.EmitArr(iL, types, typeof(object)); iL.Emit(OpCodes.Callvirt, typeof(AspectContextBody).GetMethod($"set_{nameof(AspectContextBody.MethodValues)}")); // ② 方法执行前 iL.Emit(OpCodes.Ldarg_0); iL.Emit(OpCodes.Ldfld, fieldBuilder); iL.Emit(OpCodes.Ldloc_0); iL.Emit(OpCodes.Callvirt, actionAttr.GetMethod(nameof(ActionAttribute.Before))); iL.Emit(OpCodes.Nop); // ③ 执行方法 if (returnType != typeof(void)) { iL.Emit(OpCodes.Ldloc_0); // aspectContextBody } iL.Emit(OpCodes.Ldarg_0); // 如果此方法没有参数 if (types.Length == 0) { MethodParamters(types.Length, iL); } else { MethodProxyParamters(methodInfo, iL, typeof(AspectContextBody).GetMethod($"get_{nameof(AspectContextBody.MethodValues)}")); } iL.Emit(OpCodes.Call, methodInfo); if (returnType != typeof(void)) { // 将返回结果存储到上下文中 // 值类型需要装箱 if (returnType.IsValueType) { iL.Emit(OpCodes.Box, returnType); } iL.Emit(OpCodes.Callvirt, typeof(AspectContextBody).GetMethod($"set_{nameof(AspectContextBody.MethodResult)}")); } // ④ 执行方法后 iL.Emit(OpCodes.Ldarg_0); iL.Emit(OpCodes.Ldfld, fieldBuilder); iL.Emit(OpCodes.Ldloc_0); iL.Emit(OpCodes.Callvirt, actionAttr.GetMethod(nameof(ActionAttribute.After))); if (returnType != typeof(void)) { if (returnType.IsValueType) { iL.Emit(OpCodes.Unbox_Any, methodInfo.ReturnType); } else if (returnType != typeof(object)) { iL.Emit(OpCodes.Castclass, methodInfo.ReturnType); } iL.Emit(OpCodes.Stloc_1); iL.Emit(OpCodes.Ldloc_1); // 取出堆栈中的返回值 } else { iL.Emit(OpCodes.Pop); } // ⑤ iL.Emit(OpCodes.Ret); }
/// <summary> /// 拦截 Action 并且生成类型 /// </summary> /// <typeparam name="TType">被代理的类</typeparam> /// <param name="parentType">父类</param> /// <param name="typeBuilder">生成器</param> /// <param name="Inherit">是否属于类继承</param> /// <param name="noAction">非嵌入式代理时</param> public static Type ActionInterceptor(Type parentType, TypeBuilder typeBuilder, bool Inherit, NoActionAttributeModel noAction = null) { // 生成字段,用于存放拦截的上下文信息 FieldBuilder aspectContextField = typeBuilder.DefineField("_" + nameof(AspectContextBody), typeof(AspectContext), FieldAttributes.Private | FieldAttributes.InitOnly); // 存储类成员使用的特性拦截器 Dictionary <Type, FieldBuilder> fieldList; var properties = parentType.GetProperties(); var methods = parentType.GetMethods(); fieldList = noAction == null?GetActionAttribute(properties, methods, typeBuilder) : GetActionAttribute(typeBuilder, noAction); ConstructorInfo[] constructorInfos = parentType.GetConstructors(); // 代理类实现与被代理类一致的构造函数 // 代理类初始化各个拦截器 foreach (var item in constructorInfos) { ParameterInfo[] paramTypes = item.GetParameters(); var constructorBuilder = typeBuilder.DefineConstructor( item.Attributes, item.CallingConvention, paramTypes.Select(x => x.ParameterType).ToArray()); var conIL = constructorBuilder.GetILGenerator(); if (paramTypes.Length != 0) { foreach (var itemtmp in paramTypes) { conIL.DeclareLocal(itemtmp.ParameterType); } } // 实例函数使用 从 Ldarg.1 开始 // Ldarg.0 属于 this conIL.Emit(OpCodes.Ldarg_0); // 三个步骤: // * 处理构造函数参数 // * 调用被代理类的构造函数并传递参数 // * 实例化拦截器上下文、为上下文设置属性、构造拦截器 // 如果构造函数有参数的话 if (paramTypes.Length > 0) { MethodParamters(paramTypes.Length, conIL);// 处理所有参数 } // 调用父类的构造函数 conIL.Emit(OpCodes.Call, item); // 实例化上下文 conIL.Emit(OpCodes.Ldarg_0); // 将索引为 0 的自变量加载到计算堆栈上。 conIL.Emit(OpCodes.Newobj, typeof(AspectContextBody).GetConstructor(new Type[0] { })); conIL.Emit(OpCodes.Stfld, aspectContextField); // 用新值替换在对象引用或指针的字段中存储的值。 // 为上下文设置属性 // 设置当前代理类型 conIL.Emit(OpCodes.Ldarg_0); conIL.Emit(OpCodes.Ldfld, aspectContextField); conIL.Emit(OpCodes.Castclass, typeof(AspectContextBody)); conIL.Emit(OpCodes.Ldarg_0); conIL.Emit(OpCodes.Call, parentType.GetMethod(nameof(GetType))); conIL.Emit(OpCodes.Callvirt, typeof(AspectContextBody).GetMethod($"set_{nameof(AspectContextBody.Type)}")); // 设置构造函数参数列表 conIL.Emit(OpCodes.Ldarg_0); conIL.Emit(OpCodes.Ldfld, aspectContextField); conIL.Emit(OpCodes.Castclass, typeof(AspectContextBody)); EmitHelper.EmitArr(conIL, paramTypes, typeof(object)); conIL.Emit(OpCodes.Callvirt, typeof(AspectContextBody).GetMethod($"set_{nameof(AspectContextBody.ConstructorParamters)}")); // 实例化所有拦截器 NewConstructor(conIL, fieldList); conIL.Emit(OpCodes.Ret); } // 代理拦截方法 foreach (var item in methods) { // 判断是否为侵入式代理 // 是否设置了拦截器的方法 ActionAttribute actionAttr; Type actionAttrType; if (noAction == null) { actionAttr = (ActionAttribute)item.GetCustomAttributes().FirstOrDefault(x => x.GetType().BaseType == typeof(ActionAttribute)); if (actionAttr is null) { continue; } actionAttrType = actionAttr.GetType(); } else { string actionName; if (!noAction.MethodNames.TryGetValue(item, out actionName)) { continue; } actionAttrType = noAction.Actions[actionName]; } // 获取方法的参数 Type[] types = item.GetParameters().Select(x => x.ParameterType).ToArray(); Type returnType = item.ReturnType; MethodBuilder methodBuilder = typeBuilder.DefineMethod( item.Name, MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig, CallingConventions.Standard, returnType, types); // 判断是否为泛型方法并生成泛型类型 bool isGeneric = EmitHelper.CreateGenericMethod(methodBuilder, item); var iL = methodBuilder.GetILGenerator(); // 生成代理方法 MethodProxy(iL, item, aspectContextField, fieldList[actionAttrType], actionAttrType); // 如果属于继承,则需要重写方法 if (Inherit) { typeBuilder.DefineMethodOverride(methodBuilder, item); } } // 代理拦截属性 foreach (var item in properties) { // 四种情况:没有设置拦截器、属性设置拦截器、属性的get设置拦截器、属性的set设置拦截器 // 不管构造器是否为私有都可以代理 // 是否设置了拦截器的方法 int mode = 0; MethodInfo getMethodInfo = default; MethodInfo setMethodInfo = default; // 判断属性有没有使用拦截器 var actionAttr = (ActionAttribute)item.GetCustomAttributes().FirstOrDefault(x => x.GetType().BaseType == typeof(ActionAttribute)); if (item.CanRead) { getMethodInfo = item.GetGetMethod(true); } if (item.CanWrite) { setMethodInfo = item.GetSetMethod(true); } if (actionAttr is null) { mode = 0b000; if (getMethodInfo != null) { if (getMethodInfo.GetCustomAttributes().FirstOrDefault(x => x.GetType().BaseType == typeof(ActionAttribute)) != null) { mode |= 0b001; } } if (setMethodInfo != null) { if ((ActionAttribute)setMethodInfo.GetCustomAttributes().FirstOrDefault(x => x.GetType().BaseType == typeof(ActionAttribute)) != null) { mode |= 0b010; } } } else { mode = 0b001 | 0b010; } if (mode == 0b000) { continue; } // 代理属性 switch (mode) { case 0b11: GetBuilder(); SetBuilder(); break; case 0b001: GetBuilder(); break; case 0b010: SetBuilder(); break; } void GetBuilder() { MethodBuilder setMethodBuilder = typeBuilder.DefineMethod( getMethodInfo.Name, MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig, getMethodInfo.CallingConvention, getMethodInfo.ReturnType, null); PropertyGetProxy(setMethodBuilder.GetILGenerator(), parentType, getMethodInfo, item, aspectContextField, fieldList[actionAttr.GetType()], actionAttr); } void SetBuilder() { MethodBuilder getMethodBuilder = typeBuilder.DefineMethod( setMethodInfo.Name, MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig, setMethodInfo.CallingConvention, setMethodInfo.ReturnType, setMethodInfo.GetParameters().Select(x => x.ParameterType).ToArray()); PropertyGetProxy(getMethodBuilder.GetILGenerator(), parentType, setMethodInfo, item, aspectContextField, fieldList[actionAttr.GetType()], actionAttr); } } return(typeBuilder.CreateTypeInfo()); }