using System; using System.Linq; using System.Reflection; using System.Reflection.Emit; namespace SHJX.Service.Common.Proxy { /// /// 代理类 /// public static class Proxy { public static object NewProxyInstance(Type realObj, object proxyObj) { string nameOfAssembly = realObj.Name + "ProxyAssembly"; string nameOfModule = realObj.Name + "ProxyModule"; string nameOfType = realObj.Name + "Proxy"; var assemblyName = new AssemblyName(nameOfAssembly); var assembly = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run); var moduleBuilder = assembly.DefineDynamicModule(nameOfModule); var typeBuilder = moduleBuilder.DefineType(nameOfType, TypeAttributes.Public | TypeAttributes.NotPublic, realObj); InjectInterceptor(realObj, typeBuilder, proxyObj); var t = typeBuilder.CreateType(); return Activator.CreateInstance(t); } private static void InjectInterceptor(Type type, TypeBuilder typeBuilder, object proxy) { var fieldInterceptor = typeBuilder.DefineField("_interceptor", proxy.GetType(), FieldAttributes.Private); var constructorBuilder = typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, null); var ilOfCtor = constructorBuilder.GetILGenerator(); ilOfCtor.Emit(OpCodes.Ldarg_0); ilOfCtor.Emit(OpCodes.Newobj, proxy.GetType().GetConstructor(Array.Empty())!); ilOfCtor.Emit(OpCodes.Stfld, fieldInterceptor); ilOfCtor.Emit(OpCodes.Ret); var methodsOfType = type.GetMethods(BindingFlags.Public | BindingFlags.Instance); foreach (var method in methodsOfType) { var methodParameterTypes = method.GetParameters().Select(p => p.ParameterType).ToArray(); var attr = MethodAttributes.Public | MethodAttributes.Virtual; var methodBuilder = typeBuilder.DefineMethod(method.Name, attr, CallingConventions.Standard, method.ReturnType, methodParameterTypes); var ilOfMethod = methodBuilder.GetILGenerator(); ilOfMethod.Emit(OpCodes.Ldarg_0); ilOfMethod.Emit(OpCodes.Ldfld, fieldInterceptor); ilOfMethod.Emit(OpCodes.Newobj, type.GetConstructor(Array.Empty())!); ilOfMethod.Emit(OpCodes.Ldstr, method.Name); var parameters = ilOfMethod.DeclareLocal(typeof(object[])); ilOfMethod.Emit(OpCodes.Ldc_I4, methodParameterTypes.Length); ilOfMethod.Emit(OpCodes.Newarr, typeof(object)); ilOfMethod.Emit(OpCodes.Stloc, parameters); for (var j = 0; j < methodParameterTypes.Length; j++) { ilOfMethod.Emit(OpCodes.Ldloc, parameters); ilOfMethod.Emit(OpCodes.Ldc_I4, j); ilOfMethod.Emit(OpCodes.Ldarg, j + 1); ilOfMethod.Emit(OpCodes.Stelem_Ref); } ilOfMethod.Emit(OpCodes.Ldloc, parameters); ilOfMethod.Emit(OpCodes.Callvirt, proxy.GetType().GetMethod("Invoke")!); if (method.ReturnType == typeof(void)) { ilOfMethod.Emit(OpCodes.Pop); } ilOfMethod.Emit(OpCodes.Ret); } } } }