LearningEmit
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

Program.cs 5.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Linq;
  5. using System.Reflection;
  6. using System.Reflection.Emit;
  7. namespace EmitCreateDynamicProxy
  8. {
  9. class Program
  10. {
  11. static void Main(string[] args)
  12. {
  13. //var command = Proxy.Of<Command>();
  14. //command.Execute();
  15. //Console.WriteLine("Hi, Dennis, great, we got the interceptor works.");
  16. //Console.ReadLine();
  17. Model m = DynamicProxyGenerator.CreateDynamicProxy<Model>(true);
  18. var pc = m as INotifyPropertyChanged;
  19. pc.PropertyChanged += Pc_PropertyChanged;
  20. m.Name = "ddd";
  21. var d = new DDD();
  22. //d.PropertyChanged += Pc_PropertyChanged;
  23. d.Name = "nnn";
  24. //var x = new M();
  25. //x.Name = "000";
  26. Console.WriteLine("........");
  27. Console.ReadKey();
  28. }
  29. private static void Pc_PropertyChanged(object sender, PropertyChangedEventArgs e)
  30. {
  31. Console.WriteLine($"PropertyChanged {e.PropertyName}");
  32. }
  33. }
  34. public class Command
  35. {
  36. public virtual void Execute()
  37. {
  38. Console.WriteLine("Command executing...");
  39. Console.WriteLine("Hello Kitty!");
  40. Console.WriteLine("Command executed.");
  41. }
  42. }
  43. public class Interceptor
  44. {
  45. public object Invoke(object @object, string @method, object[] parameters)
  46. {
  47. Console.WriteLine(
  48. string.Format("Interceptor does something before invoke [{0}]...", @method));
  49. var retObj = @object.GetType().GetMethod(@method).Invoke(@object, parameters);
  50. Console.WriteLine(
  51. string.Format("Interceptor does something after invoke [{0}]...", @method));
  52. return retObj;
  53. }
  54. }
  55. public class Proxy
  56. {
  57. public static T Of<T>() where T : class, new()
  58. {
  59. string nameOfAssembly = typeof(T).Name + "ProxyAssembly";
  60. string nameOfModule = typeof(T).Name + "ProxyModule";
  61. string nameOfType = typeof(T).Name + "Proxy";
  62. var assemblyName = new AssemblyName(nameOfAssembly);
  63. var assembly = AppDomain.CurrentDomain
  64. .DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
  65. var moduleBuilder = assembly.DefineDynamicModule(nameOfModule);
  66. var typeBuilder = moduleBuilder.DefineType(
  67. nameOfType, TypeAttributes.Public, typeof(T));
  68. InjectInterceptor<T>(typeBuilder);
  69. var t = typeBuilder.CreateType();
  70. return Activator.CreateInstance(t) as T;
  71. }
  72. private static void InjectInterceptor<T>(TypeBuilder typeBuilder)
  73. {
  74. // ---- define fields ----
  75. var fieldInterceptor = typeBuilder.DefineField(
  76. "_interceptor", typeof(Interceptor), FieldAttributes.Private);
  77. // ---- define costructors ----
  78. var constructorBuilder = typeBuilder.DefineConstructor(
  79. MethodAttributes.Public, CallingConventions.Standard, null);
  80. var ilOfCtor = constructorBuilder.GetILGenerator();
  81. ilOfCtor.Emit(OpCodes.Ldarg_0);
  82. ilOfCtor.Emit(OpCodes.Newobj, typeof(Interceptor).GetConstructor(new Type[0]));
  83. ilOfCtor.Emit(OpCodes.Stfld, fieldInterceptor);
  84. ilOfCtor.Emit(OpCodes.Ret);
  85. // ---- define methods ----
  86. var methodsOfType = typeof(T).GetMethods(BindingFlags.Public | BindingFlags.Instance);
  87. for (var i = 0; i < methodsOfType.Length; i++)
  88. {
  89. var method = methodsOfType[i];
  90. var methodParameterTypes =
  91. method.GetParameters().Select(p => p.ParameterType).ToArray();
  92. var methodBuilder = typeBuilder.DefineMethod(
  93. method.Name,
  94. MethodAttributes.Public | MethodAttributes.Virtual,
  95. CallingConventions.Standard,
  96. method.ReturnType,
  97. methodParameterTypes);
  98. var ilOfMethod = methodBuilder.GetILGenerator();
  99. ilOfMethod.Emit(OpCodes.Ldarg_0);
  100. ilOfMethod.Emit(OpCodes.Ldfld, fieldInterceptor);
  101. // create instance of T
  102. ilOfMethod.Emit(OpCodes.Newobj, typeof(T).GetConstructor(new Type[0]));
  103. ilOfMethod.Emit(OpCodes.Ldstr, method.Name);
  104. // build the method parameters
  105. if (methodParameterTypes == null)
  106. {
  107. ilOfMethod.Emit(OpCodes.Ldnull);
  108. }
  109. else
  110. {
  111. var parameters = ilOfMethod.DeclareLocal(typeof(object[]));
  112. ilOfMethod.Emit(OpCodes.Ldc_I4, methodParameterTypes.Length);
  113. ilOfMethod.Emit(OpCodes.Newarr, typeof(object));
  114. ilOfMethod.Emit(OpCodes.Stloc, parameters);
  115. for (var j = 0; j < methodParameterTypes.Length; j++)
  116. {
  117. ilOfMethod.Emit(OpCodes.Ldloc, parameters);
  118. ilOfMethod.Emit(OpCodes.Ldc_I4, j);
  119. ilOfMethod.Emit(OpCodes.Ldarg, j + 1);
  120. ilOfMethod.Emit(OpCodes.Stelem_Ref);
  121. }
  122. ilOfMethod.Emit(OpCodes.Ldloc, parameters);
  123. }
  124. // call Invoke() method of Interceptor
  125. ilOfMethod.Emit(OpCodes.Callvirt, typeof(Interceptor).GetMethod("Invoke"));
  126. // pop the stack if return void
  127. if (method.ReturnType == typeof(void))
  128. {
  129. ilOfMethod.Emit(OpCodes.Pop);
  130. }
  131. // complete
  132. ilOfMethod.Emit(OpCodes.Ret);
  133. }
  134. }
  135. }
  136. }