LearningEmit
Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

Program.cs 5.4KB

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