Guest User

Untitled

a guest
Mar 13th, 2018
97
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.67 KB | None | 0 0
  1. using System.Linq;
  2. using System.Reflection;
  3. using System.Reflection.Emit;
  4.  
  5. namespace DP115Test
  6. {
  7. using System;
  8.  
  9. class Program
  10. {
  11. static void Main(string[] args)
  12. {
  13. var assembly = AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName("Foo"), AssemblyBuilderAccess.RunAndSave);
  14. var type = assembly
  15. .DefineDynamicModule("FooModule", "FooModule.dll", true)
  16. .DefineType("AClass", TypeAttributes.Public | TypeAttributes.AutoClass | TypeAttributes.AnsiClass | TypeAttributes.BeforeFieldInit, typeof(object), new[] { typeof(IFoo) });
  17. var method = type.DefineMethod("IFoo.SomeMethod", MethodAttributes.Private | MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Virtual | MethodAttributes.Final, CallingConventions.HasThis);
  18. var typeParameters = method.DefineGenericParameters(new[] { "TBase", "TInherited" });
  19. typeParameters[1].SetBaseTypeConstraint(typeParameters[0]);
  20. type.DefineMethodOverride(method, typeof(IFoo).GetMethods().Single());
  21. ConstructorBuilder nestedCtor;
  22. MethodBuilder nestedMethod;
  23. TypeBuilder nested = GenerateInvocationType(type, method, out nestedCtor, out nestedMethod);
  24. GenerateSomeMethod(method, nested, typeParameters, nestedCtor, nestedMethod);
  25. var createdType = type.CreateType();
  26. nested.CreateType();
  27. assembly.Save("FooModule.dll");
  28.  
  29. var instance = Activator.CreateInstance(createdType) as IFoo;
  30. //instance.SomeMethod<IComparable<string>, string>(); // NOTE: will currently yield StackOverflowException
  31. }
  32.  
  33. private static TypeBuilder GenerateInvocationType(TypeBuilder type, MethodBuilder method, out ConstructorBuilder nestedCtor, out MethodBuilder nestedMethod)
  34. {
  35. var builder = type.DefineNestedType("NestedClass",
  36. TypeAttributes.AutoLayout | TypeAttributes.AnsiClass |
  37. TypeAttributes.Serializable |
  38. TypeAttributes.Sealed | TypeAttributes.NestedAssembly, typeof (object),
  39. new[] {typeof (IInvocation)});
  40. var typeParameters = builder.DefineGenericParameters(new[] {"TBase_NestedType", "TInherited_NestedType"});
  41. typeParameters[1].SetBaseTypeConstraint(typeParameters[0]);
  42. var target = builder.DefineField("target", type, FieldAttributes.InitOnly | FieldAttributes.Private);
  43. nestedCtor = GenerateCtor(type, builder, target);
  44. nestedMethod = GenerateInvokeOnTarget(type, builder, target, typeParameters, method);
  45. return builder;
  46. }
  47.  
  48. private static MethodBuilder GenerateInvokeOnTarget(TypeBuilder type, TypeBuilder builder, FieldBuilder target, GenericTypeParameterBuilder[] parameters, MethodBuilder methodToInvoke)
  49. {
  50. var method = builder.DefineMethod("InvokeOnTarget",
  51. MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.NewSlot |
  52. MethodAttributes.Virtual | MethodAttributes.Final, CallingConventions.HasThis);
  53. method.SetReturnType(typeof(void));
  54. var generator = method.GetILGenerator();
  55. generator.Emit(OpCodes.Ldarg_0);
  56. generator.Emit(OpCodes.Ldfld, target);
  57. generator.Emit(OpCodes.Callvirt, methodToInvoke.MakeGenericMethod(parameters));
  58. generator.Emit(OpCodes.Ret);
  59. return method;
  60. }
  61.  
  62. private static ConstructorBuilder GenerateCtor(TypeBuilder type, TypeBuilder builder, FieldBuilder target)
  63. {
  64. var constructor =
  65. builder.DefineConstructor(MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName,
  66. CallingConventions.HasThis, new Type[] {type});
  67. var generator = constructor.GetILGenerator();
  68. generator.Emit(OpCodes.Ldarg_0);
  69. generator.Emit(OpCodes.Call, typeof (object).GetConstructors().Single());
  70. generator.Emit(OpCodes.Ldarg_0);
  71. generator.Emit(OpCodes.Ldarg_1);
  72. generator.Emit(OpCodes.Stfld, target);
  73. generator.Emit(OpCodes.Ret);
  74. return constructor;
  75. }
  76.  
  77. private static void GenerateSomeMethod(MethodBuilder method, TypeBuilder invocation, GenericTypeParameterBuilder[] parameters, ConstructorBuilder nestedCtor, MethodBuilder nestedMethod)
  78. {
  79. method.SetReturnType(typeof(void));
  80.  
  81. var genericType = invocation.MakeGenericType(parameters);
  82. var constructor = TypeBuilder.GetConstructor(genericType, nestedCtor);
  83. var methodInfo = TypeBuilder.GetMethod(genericType,nestedMethod);
  84. var generator = method.GetILGenerator();
  85. generator.Emit(OpCodes.Ldarg_0);
  86. generator.Emit(OpCodes.Newobj, constructor);
  87. generator.Emit(OpCodes.Callvirt, methodInfo);
  88. generator.Emit(OpCodes.Ret);
  89. }
  90. }
  91.  
  92. public interface IFoo
  93. {
  94. void SomeMethod<TBase, TInherited>() where TInherited : TBase;
  95. }
  96.  
  97. public interface IInvocation
  98. {
  99. void InvokeOnTarget();
  100. }
  101. }
Add Comment
Please, Sign In to add comment