/// <summary> /// DefineMethod /// </summary> /// <param name="name"></param> /// <param name="attributes"></param> /// <param name="callingConvention"></param> /// <param name="returnType"></param> /// <param name="parameterTypes"></param> /// <returns></returns> public ILGenerator DefineMethod(string name, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, ParameterInfo[] parameterInfos) { if (string.IsNullOrEmpty(name)) { throw new ArgumentNullException("name"); } if (returnType == null) { throw new ArgumentNullException("returnType"); } if (parameterInfos == null) { throw new ArgumentNullException("parameterInfos"); } Type[] parameterTypes = ProxyUtil.GetType(parameterInfos); var methodBuilder = this.typeBuilder.DefineMethod(name, attributes, callingConvention, returnType, parameterTypes); for (int i = 0; i < parameterInfos.Length; i++) { var parameterInfo = parameterInfos[i]; var parameterBuilder = methodBuilder.DefineParameter(parameterInfo.Position + 1, parameterInfo.Attributes, parameterInfo.Name); if ((parameterInfo.Attributes & ParameterAttributes.HasDefault) == ParameterAttributes.HasDefault) { parameterBuilder.SetConstant(parameterInfo.DefaultValue); } } ILGenerator il = methodBuilder.GetILGenerator(); return(il); }
private Type GetClassProxyType(Type targetType) { if (targetType == null) { throw new ArgumentNullException("targetType"); } if (!targetType.IsClass) { throw new ArgumentException(targetType.FullName + "不是class!", "targetType"); } if (!targetType.IsPublic) { throw new ArgumentException(targetType.FullName + "不是 public!", "targetType"); } if (targetType.IsAbstract) { throw new ArgumentException(targetType.FullName + "不能是abstract!", "targetType"); } if (targetType.IsGenericType && targetType.IsGenericTypeDefinition) { throw new ArgumentException(targetType.FullName + "不能是GenericTypeDefinition!", "targetType"); } if (targetType.IsSealed) { throw new ArgumentException(targetType.FullName + "不能是 sealed!", "targetType"); } if (targetType.IsArray) { throw new ArgumentException(targetType.FullName + "不能是 array!", "targetType"); } var targetCtors = targetType.GetConstructors(); if (targetCtors.Length == 0) { throw new ArgumentException(targetType.FullName + "没有公共构造函数!", "targetType"); } Type proxyType = null; if (this.m_classProxyDic.TryGetValue(targetType, out proxyType)) { return(proxyType); } var interfaceTypes = targetType.GetInterfaces(); var typeDynamicBuilder = this.assemblyDynamicBuilder.DefineType(this.assemblyDynamicBuilder.GetDynamicName(targetType), targetType.Attributes, targetType, interfaceTypes); typeDynamicBuilder.AddInterfaceImplementation(typeof(IProxy)); var targetTypeField = typeDynamicBuilder.DefineField("__m_targetType", typeof(Type), FieldAttributes.Private); var aopFuncsField = typeDynamicBuilder.DefineField("__m_aopFuncs", typeof(Func <IAop>[]), FieldAttributes.Private); // 构造器 { MethodAttributes methattr = MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName; CallingConventions calling = CallingConventions.Standard | CallingConventions.HasThis; foreach (var baseCtor in targetCtors) { var paramets = ProxyUtil.GetParameterType(baseCtor); ILGenerator il = typeDynamicBuilder.DefineConstructor(methattr, calling, paramets); il.Emit(OpCodes.Ldarg_0); for (int i = 0; i < paramets.Length; i++) { il.Emit(OpCodes.Ldarg, i + 1); } il.Emit(OpCodes.Call, baseCtor); il.Emit(OpCodes.Ret); } } // IProxy { MethodAttributes methattr = MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig | MethodAttributes.NewSlot; CallingConventions calling = CallingConventions.Standard | CallingConventions.HasThis; // SetTargetTypeMethod var il = typeDynamicBuilder.DefineMethod(ProxyUtil.SetTargetTypeMethod.Name, methattr, calling, ProxyUtil.SetTargetTypeMethod.ReturnType, new Type[] { typeof(Type) }); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Stfld, targetTypeField); il.Emit(OpCodes.Ret); //GetTargetTypeMethod il = typeDynamicBuilder.DefineMethod(ProxyUtil.GetTargetTypeMethod.Name, methattr, calling, ProxyUtil.GetTargetTypeMethod.ReturnType, Type.EmptyTypes); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldfld, targetTypeField); il.Emit(OpCodes.Ret); //SetAopFuncMethod il = typeDynamicBuilder.DefineMethod(ProxyUtil.SetAopFuncMethod.Name, methattr, calling, ProxyUtil.SetAopFuncMethod.ReturnType, new Type[] { typeof(Func <IAop>[]) }); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Stfld, aopFuncsField); il.Emit(OpCodes.Ret); //GetAopFuncMethod il = typeDynamicBuilder.DefineMethod(ProxyUtil.GetAopFuncMethod.Name, methattr, calling, ProxyUtil.GetAopFuncMethod.ReturnType, Type.EmptyTypes); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldfld, aopFuncsField); il.Emit(OpCodes.Ret); } //方法 var methods = this.GetAllMethod(targetType); //public hidebysig newslot virtual final MethodAttributes newMethodAttr = MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig | MethodAttributes.NewSlot; foreach (var baseMethod in methods) { var intefacemethlist = this.GetOverrideMethods(baseMethod, interfaceTypes); if (!baseMethod.IsVirtual && intefacemethlist.Count == 0 || baseMethod.IsFinal) { continue; } var parameterInfos = baseMethod.GetParameters(); var parameterTypes = ProxyUtil.GetType(parameterInfos); MethodAttributes methattr = MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig; CallingConventions calling = CallingConventions.Standard | CallingConventions.HasThis; if (baseMethod.Attributes == newMethodAttr || baseMethod.Attributes == (MethodAttributes.Public | MethodAttributes.HideBySig)) { methattr = newMethodAttr;// MethodAttributes.Public | MethodAttributes.HideBySig; } ILGenerator il = typeDynamicBuilder.DefineMethod(baseMethod.Name, methattr, calling, baseMethod.ReturnType, parameterInfos); #region 定义局部变量 var contextLocal = il.DeclareLocal(typeof(AopContext)); var proxyMethodBaseLocal = il.DeclareLocal(typeof(MethodBase)); var baseMethodLocal = il.DeclareLocal(typeof(MethodInfo)); var argsLocal = il.DeclareLocal(typeof(object[])); var exLocal = il.DeclareLocal(typeof(Exception)); LocalBuilder resultLocal = null;//5 if (baseMethod.ReturnType != null && baseMethod.ReturnType != typeof(void)) { resultLocal = il.DeclareLocal(baseMethod.ReturnType); } Label execEndLabel = il.DefineLabel(); Label resultEndLabel = il.DefineLabel(); Label exEndLabel = il.DefineLabel(); #endregion #region 初始局部变量 il.Emit(OpCodes.Ldnull); il.Emit(OpCodes.Stloc, contextLocal); if (resultLocal != null) { if (!baseMethod.ReturnType.IsValueType) { il.Emit(OpCodes.Ldnull); il.Emit(OpCodes.Stloc, resultLocal); } } #endregion il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldfld, aopFuncsField); il.Emit(OpCodes.Ldlen); il.Emit(OpCodes.Ldc_I4_0); il.Emit(OpCodes.Cgt_Un); il.Emit(OpCodes.Brfalse, execEndLabel); il.Emit(OpCodes.Newobj, typeof(AopContext).GetConstructor(Type.EmptyTypes)); il.Emit(OpCodes.Stloc, contextLocal); il.Emit(OpCodes.Call, typeof(MethodBase).GetMethod("GetCurrentMethod", BindingFlags.Static | BindingFlags.Public)); il.Emit(OpCodes.Stloc, proxyMethodBaseLocal); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldfld, targetTypeField); //il.Emit(OpCodes.Ldloc, methodBaseLocal); //il.Emit(OpCodes.Callvirt, typeof(MemberInfo).GetMethod("get_Name")); il.Emit(OpCodes.Ldstr, baseMethod.Name); il.Emit(OpCodes.Ldloc, proxyMethodBaseLocal); il.Emit(OpCodes.Call, ProxyUtil.GetParameterTypeMethod); il.Emit(OpCodes.Callvirt, typeof(Type).GetMethod("GetMethod", new Type[] { typeof(string), typeof(Type[]) })); il.Emit(OpCodes.Stloc, baseMethodLocal); il.Emit(OpCodes.Ldc_I4, parameterTypes.Length); il.Emit(OpCodes.Newarr, typeof(Object)); il.Emit(OpCodes.Stloc, argsLocal); for (int i = 0; i < parameterTypes.Length; i++) { il.Emit(OpCodes.Ldloc, argsLocal); il.Emit(OpCodes.Ldc_I4, i); il.Emit(OpCodes.Ldarg, i + 1); if (parameterTypes[i].IsValueType) { il.Emit(OpCodes.Box, parameterTypes[i]); } il.Emit(OpCodes.Stelem_Ref); } il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldloc, baseMethodLocal); il.Emit(OpCodes.Ldloc, argsLocal); il.Emit(OpCodes.Ldloc, contextLocal); il.Emit(OpCodes.Call, ProxyUtil.OnExecutingMethod); il.MarkLabel(execEndLabel); il.Emit(OpCodes.Nop); var exBlock = il.BeginExceptionBlock(); il.Emit(OpCodes.Ldarg_0); for (int i = 0; i < parameterTypes.Length; i++) { il.Emit(OpCodes.Ldarg, i + 1); } il.Emit(OpCodes.Call, baseMethod); if (resultLocal != null) { il.Emit(OpCodes.Stloc, resultLocal); } il.BeginCatchBlock(typeof(Exception)); il.Emit(OpCodes.Stloc, exLocal); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldfld, aopFuncsField); il.Emit(OpCodes.Ldlen); il.Emit(OpCodes.Ldc_I4_0); il.Emit(OpCodes.Cgt_Un); il.Emit(OpCodes.Brfalse, exEndLabel); il.Emit(OpCodes.Ldloc, contextLocal); il.Emit(OpCodes.Ldloc, exLocal); il.Emit(OpCodes.Call, ProxyUtil.OnExceptionMethod); il.Emit(OpCodes.Nop); il.MarkLabel(exEndLabel); il.Emit(OpCodes.Ldloc, exLocal); il.Emit(OpCodes.Throw); il.EndExceptionBlock(); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldfld, aopFuncsField); il.Emit(OpCodes.Ldlen); il.Emit(OpCodes.Ldc_I4_0); il.Emit(OpCodes.Cgt_Un); il.Emit(OpCodes.Brfalse, resultEndLabel); il.Emit(OpCodes.Ldloc, contextLocal); if (resultLocal != null) { il.Emit(OpCodes.Ldloc, resultLocal); if (baseMethod.ReturnType.IsValueType) { il.Emit(OpCodes.Box, baseMethod.ReturnType); } } else { il.Emit(OpCodes.Ldnull); } il.Emit(OpCodes.Call, ProxyUtil.OnResultMethod); il.MarkLabel(resultEndLabel); il.Emit(OpCodes.Nop); if (resultLocal != null) { il.Emit(OpCodes.Ldloc, resultLocal); } il.Emit(OpCodes.Ret); } proxyType = typeDynamicBuilder.CreateType(); this.m_classProxyDic.TryAdd(targetType, proxyType); return(proxyType); }
private Type GetProxyType(Type interfaceType) { Type proxyType = null; if (interfaceType == null) { throw new ArgumentNullException("targetType"); } if (!interfaceType.IsInterface) { throw new ArgumentException(interfaceType.FullName + "不是interface!", "interfaceType"); } if (this.m_interfaceProxyDic.TryGetValue(interfaceType, out proxyType)) { return(proxyType); } var typeDynamicBuilder = this.assemblyDynamicBuilder.DefineType(this.assemblyDynamicBuilder.GetDynamicName(interfaceType), TypeAttributes.Class | TypeAttributes.Public, typeof(object), new Type[] { interfaceType }); typeDynamicBuilder.AddInterfaceImplementation(typeof(IProxy)); var targetTypeField = typeDynamicBuilder.DefineField("__m_targetType", typeof(Type), FieldAttributes.Private); var aopFuncsField = typeDynamicBuilder.DefineField("__m_aopFuncs", typeof(Func <IAop>[]), FieldAttributes.Private); var targetField = typeDynamicBuilder.DefineField("__m_target", interfaceType, FieldAttributes.Private); // 构造器 { var baseCtor = typeof(object).GetConstructor(Type.EmptyTypes); MethodAttributes methattr = MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName; CallingConventions calling = CallingConventions.Standard | CallingConventions.HasThis; ILGenerator il = typeDynamicBuilder.DefineConstructor(methattr, calling, new Type[] { interfaceType }); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Call, baseCtor); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Stfld, targetField); il.Emit(OpCodes.Ret); } // IProxy { MethodAttributes methattr = MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig | MethodAttributes.NewSlot; CallingConventions calling = CallingConventions.Standard | CallingConventions.HasThis; // SetTargetTypeMethod ILGenerator il = typeDynamicBuilder.DefineMethod(ProxyUtil.SetTargetTypeMethod.Name, methattr, calling, ProxyUtil.SetTargetTypeMethod.ReturnType, new Type[] { typeof(Type) }); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Stfld, targetTypeField); il.Emit(OpCodes.Ret); //GetTargetTypeMethod il = typeDynamicBuilder.DefineMethod(ProxyUtil.GetTargetTypeMethod.Name, methattr, calling, ProxyUtil.GetTargetTypeMethod.ReturnType, Type.EmptyTypes); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldfld, targetTypeField); il.Emit(OpCodes.Ret); //SetAopFuncMethod il = typeDynamicBuilder.DefineMethod(ProxyUtil.SetAopFuncMethod.Name, methattr, calling, ProxyUtil.SetAopFuncMethod.ReturnType, new Type[] { typeof(Func <IAop>[]) }); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Stfld, aopFuncsField); il.Emit(OpCodes.Ret); //GetAopFuncMethod il = typeDynamicBuilder.DefineMethod(ProxyUtil.GetAopFuncMethod.Name, methattr, calling, ProxyUtil.GetAopFuncMethod.ReturnType, Type.EmptyTypes); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldfld, aopFuncsField); il.Emit(OpCodes.Ret); } //方法 var methods = interfaceType.GetMethods(); foreach (var baseMethod in methods) { var parameterInfos = baseMethod.GetParameters(); var parameterTypes = ProxyUtil.GetType(parameterInfos); MethodAttributes methattr = MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig | MethodAttributes.NewSlot; CallingConventions calling = CallingConventions.Standard | CallingConventions.HasThis; ILGenerator il = typeDynamicBuilder.DefineMethod(baseMethod.Name, methattr, calling, baseMethod.ReturnType, parameterInfos); #region 定义局部变量 var contextLocal = il.DeclareLocal(typeof(AopContext)); var methodBaseLocal = il.DeclareLocal(typeof(MethodBase)); var methodLocal = il.DeclareLocal(typeof(MethodInfo)); var argsLocal = il.DeclareLocal(typeof(object[])); var exLocal = il.DeclareLocal(typeof(Exception)); LocalBuilder returnLocal = null; if (baseMethod.ReturnType != null && baseMethod.ReturnType != typeof(void)) { returnLocal = il.DeclareLocal(baseMethod.ReturnType); } Label execEndLabel = il.DefineLabel(); Label resultEndLabel = il.DefineLabel(); Label exEndLabel = il.DefineLabel(); #endregion #region 初始局部变量 il.Emit(OpCodes.Ldnull); il.Emit(OpCodes.Stloc, contextLocal); if (returnLocal != null) { if (!baseMethod.ReturnType.IsValueType) { il.Emit(OpCodes.Ldnull); il.Emit(OpCodes.Stloc, returnLocal); } } #endregion il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldfld, aopFuncsField); il.Emit(OpCodes.Ldlen); il.Emit(OpCodes.Ldc_I4_0); il.Emit(OpCodes.Cgt_Un); il.Emit(OpCodes.Brfalse, execEndLabel); il.Emit(OpCodes.Newobj, typeof(AopContext).GetConstructor(Type.EmptyTypes)); il.Emit(OpCodes.Stloc, contextLocal); il.Emit(OpCodes.Call, typeof(MethodBase).GetMethod("GetCurrentMethod", BindingFlags.Static | BindingFlags.Public)); il.Emit(OpCodes.Stloc, methodBaseLocal); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldfld, targetTypeField); //il.Emit(OpCodes.Ldloc, methodBaseLocal); //il.Emit(OpCodes.Callvirt, typeof(MemberInfo).GetMethod("get_Name")); il.Emit(OpCodes.Ldstr, baseMethod.Name); il.Emit(OpCodes.Ldloc, methodBaseLocal); il.Emit(OpCodes.Call, ProxyUtil.GetParameterTypeMethod); il.Emit(OpCodes.Callvirt, typeof(Type).GetMethod("GetMethod", new Type[] { typeof(string), typeof(Type[]) })); il.Emit(OpCodes.Stloc, methodLocal); il.Emit(OpCodes.Ldc_I4, parameterTypes.Length); il.Emit(OpCodes.Newarr, typeof(Object)); il.Emit(OpCodes.Stloc, argsLocal); for (int i = 0; i < parameterTypes.Length; i++) { il.Emit(OpCodes.Ldloc, argsLocal); il.Emit(OpCodes.Ldc_I4, i); il.Emit(OpCodes.Ldarg, i + 1); if (parameterTypes[i].IsValueType) { il.Emit(OpCodes.Box, parameterTypes[i]); } il.Emit(OpCodes.Stelem_Ref); } il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldloc, methodLocal); il.Emit(OpCodes.Ldloc, argsLocal); il.Emit(OpCodes.Ldloc, contextLocal); il.Emit(OpCodes.Call, ProxyUtil.OnExecutingMethod); il.MarkLabel(execEndLabel); il.Emit(OpCodes.Nop); var exBlock = il.BeginExceptionBlock(); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldfld, targetField); for (int i = 0; i < parameterTypes.Length; i++) { il.Emit(OpCodes.Ldarg, i + 1); } il.Emit(OpCodes.Call, baseMethod); if (returnLocal != null) { il.Emit(OpCodes.Stloc, returnLocal); } il.BeginCatchBlock(typeof(Exception)); il.Emit(OpCodes.Stloc, exLocal); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldfld, aopFuncsField); il.Emit(OpCodes.Ldlen); il.Emit(OpCodes.Ldc_I4_0); il.Emit(OpCodes.Cgt_Un); il.Emit(OpCodes.Brfalse, exEndLabel); il.Emit(OpCodes.Ldloc, contextLocal); il.Emit(OpCodes.Ldloc, exLocal); il.Emit(OpCodes.Call, ProxyUtil.OnExceptionMethod); il.Emit(OpCodes.Nop); il.MarkLabel(exEndLabel); il.Emit(OpCodes.Ldloc, exLocal); il.Emit(OpCodes.Throw); il.EndExceptionBlock(); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldfld, aopFuncsField); il.Emit(OpCodes.Ldlen); il.Emit(OpCodes.Ldc_I4_0); il.Emit(OpCodes.Cgt_Un); il.Emit(OpCodes.Brfalse, resultEndLabel); il.Emit(OpCodes.Ldloc, contextLocal); if (returnLocal != null) { il.Emit(OpCodes.Ldloc, returnLocal); if (baseMethod.ReturnType.IsValueType) { il.Emit(OpCodes.Box, baseMethod.ReturnType); } } else { il.Emit(OpCodes.Ldnull); } il.Emit(OpCodes.Call, ProxyUtil.OnResultMethod); il.MarkLabel(resultEndLabel); il.Emit(OpCodes.Nop); if (returnLocal != null) { il.Emit(OpCodes.Ldloc, returnLocal); } il.Emit(OpCodes.Ret); } proxyType = typeDynamicBuilder.CreateType(); this.m_interfaceProxyDic.TryAdd(interfaceType, proxyType); return(proxyType); }