Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System.Linq;
- using System.Reflection;
- using System.Reflection.Emit;
- namespace DP115Test
- {
- using System;
- class Program
- {
- static void Main(string[] args)
- {
- var assembly = AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName("Foo"), AssemblyBuilderAccess.RunAndSave);
- var type = assembly
- .DefineDynamicModule("FooModule", "FooModule.dll", true)
- .DefineType("AClass", TypeAttributes.Public | TypeAttributes.AutoClass | TypeAttributes.AnsiClass | TypeAttributes.BeforeFieldInit, typeof(object), new[] { typeof(IFoo) });
- var method = type.DefineMethod("IFoo.SomeMethod", MethodAttributes.Private | MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Virtual | MethodAttributes.Final, CallingConventions.HasThis);
- var typeParameters = method.DefineGenericParameters(new[] { "TBase", "TInherited" });
- typeParameters[1].SetBaseTypeConstraint(typeParameters[0]);
- type.DefineMethodOverride(method, typeof(IFoo).GetMethods().Single());
- ConstructorBuilder nestedCtor;
- MethodBuilder nestedMethod;
- TypeBuilder nested = GenerateInvocationType(type, method, out nestedCtor, out nestedMethod);
- GenerateSomeMethod(method, nested, typeParameters, nestedCtor, nestedMethod);
- var createdType = type.CreateType();
- nested.CreateType();
- assembly.Save("FooModule.dll");
- var instance = Activator.CreateInstance(createdType) as IFoo;
- //instance.SomeMethod<IComparable<string>, string>(); // NOTE: will currently yield StackOverflowException
- }
- private static TypeBuilder GenerateInvocationType(TypeBuilder type, MethodBuilder method, out ConstructorBuilder nestedCtor, out MethodBuilder nestedMethod)
- {
- var builder = type.DefineNestedType("NestedClass",
- TypeAttributes.AutoLayout | TypeAttributes.AnsiClass |
- TypeAttributes.Serializable |
- TypeAttributes.Sealed | TypeAttributes.NestedAssembly, typeof (object),
- new[] {typeof (IInvocation)});
- var typeParameters = builder.DefineGenericParameters(new[] {"TBase_NestedType", "TInherited_NestedType"});
- typeParameters[1].SetBaseTypeConstraint(typeParameters[0]);
- var target = builder.DefineField("target", type, FieldAttributes.InitOnly | FieldAttributes.Private);
- nestedCtor = GenerateCtor(type, builder, target);
- nestedMethod = GenerateInvokeOnTarget(type, builder, target, typeParameters, method);
- return builder;
- }
- private static MethodBuilder GenerateInvokeOnTarget(TypeBuilder type, TypeBuilder builder, FieldBuilder target, GenericTypeParameterBuilder[] parameters, MethodBuilder methodToInvoke)
- {
- var method = builder.DefineMethod("InvokeOnTarget",
- MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.NewSlot |
- MethodAttributes.Virtual | MethodAttributes.Final, CallingConventions.HasThis);
- method.SetReturnType(typeof(void));
- var generator = method.GetILGenerator();
- generator.Emit(OpCodes.Ldarg_0);
- generator.Emit(OpCodes.Ldfld, target);
- generator.Emit(OpCodes.Callvirt, methodToInvoke.MakeGenericMethod(parameters));
- generator.Emit(OpCodes.Ret);
- return method;
- }
- private static ConstructorBuilder GenerateCtor(TypeBuilder type, TypeBuilder builder, FieldBuilder target)
- {
- var constructor =
- builder.DefineConstructor(MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName,
- CallingConventions.HasThis, new Type[] {type});
- var generator = constructor.GetILGenerator();
- generator.Emit(OpCodes.Ldarg_0);
- generator.Emit(OpCodes.Call, typeof (object).GetConstructors().Single());
- generator.Emit(OpCodes.Ldarg_0);
- generator.Emit(OpCodes.Ldarg_1);
- generator.Emit(OpCodes.Stfld, target);
- generator.Emit(OpCodes.Ret);
- return constructor;
- }
- private static void GenerateSomeMethod(MethodBuilder method, TypeBuilder invocation, GenericTypeParameterBuilder[] parameters, ConstructorBuilder nestedCtor, MethodBuilder nestedMethod)
- {
- method.SetReturnType(typeof(void));
- var genericType = invocation.MakeGenericType(parameters);
- var constructor = TypeBuilder.GetConstructor(genericType, nestedCtor);
- var methodInfo = TypeBuilder.GetMethod(genericType,nestedMethod);
- var generator = method.GetILGenerator();
- generator.Emit(OpCodes.Ldarg_0);
- generator.Emit(OpCodes.Newobj, constructor);
- generator.Emit(OpCodes.Callvirt, methodInfo);
- generator.Emit(OpCodes.Ret);
- }
- }
- public interface IFoo
- {
- void SomeMethod<TBase, TInherited>() where TInherited : TBase;
- }
- public interface IInvocation
- {
- void InvokeOnTarget();
- }
- }
Add Comment
Please, Sign In to add comment