Proxy.cs 3.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. using System;
  2. using System.Linq;
  3. using System.Reflection;
  4. using System.Reflection.Emit;
  5. namespace SHJX.Service.Common.Proxy
  6. {
  7. /// <summary>
  8. /// 代理类
  9. /// </summary>
  10. public static class Proxy
  11. {
  12. public static object NewProxyInstance(Type realObj, object proxyObj)
  13. {
  14. string nameOfAssembly = realObj.Name + "ProxyAssembly";
  15. string nameOfModule = realObj.Name + "ProxyModule";
  16. string nameOfType = realObj.Name + "Proxy";
  17. var assemblyName = new AssemblyName(nameOfAssembly);
  18. var assembly = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
  19. var moduleBuilder = assembly.DefineDynamicModule(nameOfModule);
  20. var typeBuilder = moduleBuilder.DefineType(nameOfType, TypeAttributes.Public | TypeAttributes.NotPublic, realObj);
  21. InjectInterceptor(realObj, typeBuilder, proxyObj);
  22. var t = typeBuilder.CreateType();
  23. return Activator.CreateInstance(t);
  24. }
  25. private static void InjectInterceptor(Type type, TypeBuilder typeBuilder, object proxy)
  26. {
  27. var fieldInterceptor = typeBuilder.DefineField("_interceptor", proxy.GetType(), FieldAttributes.Private);
  28. var constructorBuilder =
  29. typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, null);
  30. var ilOfCtor = constructorBuilder.GetILGenerator();
  31. ilOfCtor.Emit(OpCodes.Ldarg_0);
  32. ilOfCtor.Emit(OpCodes.Newobj, proxy.GetType().GetConstructor(Array.Empty<Type>())!);
  33. ilOfCtor.Emit(OpCodes.Stfld, fieldInterceptor);
  34. ilOfCtor.Emit(OpCodes.Ret);
  35. var methodsOfType = type.GetMethods(BindingFlags.Public | BindingFlags.Instance);
  36. foreach (var method in methodsOfType)
  37. {
  38. var methodParameterTypes = method.GetParameters().Select(p => p.ParameterType).ToArray();
  39. var attr = MethodAttributes.Public | MethodAttributes.Virtual;
  40. var methodBuilder = typeBuilder.DefineMethod(method.Name, attr, CallingConventions.Standard,
  41. method.ReturnType, methodParameterTypes);
  42. var ilOfMethod = methodBuilder.GetILGenerator();
  43. ilOfMethod.Emit(OpCodes.Ldarg_0);
  44. ilOfMethod.Emit(OpCodes.Ldfld, fieldInterceptor);
  45. ilOfMethod.Emit(OpCodes.Newobj, type.GetConstructor(Array.Empty<Type>())!);
  46. ilOfMethod.Emit(OpCodes.Ldstr, method.Name);
  47. var parameters = ilOfMethod.DeclareLocal(typeof(object[]));
  48. ilOfMethod.Emit(OpCodes.Ldc_I4, methodParameterTypes.Length);
  49. ilOfMethod.Emit(OpCodes.Newarr, typeof(object));
  50. ilOfMethod.Emit(OpCodes.Stloc, parameters);
  51. for (var j = 0; j < methodParameterTypes.Length; j++)
  52. {
  53. ilOfMethod.Emit(OpCodes.Ldloc, parameters);
  54. ilOfMethod.Emit(OpCodes.Ldc_I4, j);
  55. ilOfMethod.Emit(OpCodes.Ldarg, j + 1);
  56. ilOfMethod.Emit(OpCodes.Stelem_Ref);
  57. }
  58. ilOfMethod.Emit(OpCodes.Ldloc, parameters);
  59. ilOfMethod.Emit(OpCodes.Callvirt, proxy.GetType().GetMethod("Invoke")!);
  60. if (method.ReturnType == typeof(void))
  61. {
  62. ilOfMethod.Emit(OpCodes.Pop);
  63. }
  64. ilOfMethod.Emit(OpCodes.Ret);
  65. }
  66. }
  67. }
  68. }