Last active
October 3, 2017 09:04
-
-
Save usausa/183823e942c79aea80b79033ecc76208 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Reflection; | |
using System.Reflection.Emit; | |
public static class DynamicActivatorFactory | |
{ | |
private static readonly AssemblyBuilder AssemblyBuilder = AssemblyBuilder.DefineDynamicAssembly( | |
new AssemblyName("DynamicActivator"), | |
AssemblyBuilderAccess.Run); | |
private static readonly ModuleBuilder ModuleBuilder = AssemblyBuilder.DefineDynamicModule("DynamicActivator"); | |
public static IActivator CreateActivator(ConstructorInfo ci) | |
{ | |
var typeBuilder = ModuleBuilder.DefineType(ci.DeclaringType.FullName + "_DynamicActivator"); | |
typeBuilder.AddInterfaceImplementation(typeof(IActivator)); | |
var methodBuilder = typeBuilder.DefineMethod( | |
nameof(IActivator.Create), | |
MethodAttributes.Public | MethodAttributes.Virtual, | |
typeof(object), | |
new[] { typeof(object[]) }); | |
typeBuilder.DefineMethodOverride(methodBuilder, typeof(IActivator).GetMethod(nameof(IActivator.Create))); | |
var il = methodBuilder.GetILGenerator(); | |
for (var i = 0; i < ci.GetParameters().Length; i++) | |
{ | |
il.Emit(OpCodes.Ldarg_1); | |
EmitLdcI4(il, i); | |
il.Emit(OpCodes.Ldelem_Ref); | |
EmitTypeConversion(il, ci.GetParameters()[i].ParameterType); | |
} | |
il.Emit(OpCodes.Newobj, ci); | |
il.Emit(OpCodes.Ret); | |
var type = typeBuilder.CreateType(); | |
return (IActivator)Activator.CreateInstance(type); | |
} | |
private static void EmitLdcI4(ILGenerator il, int i) | |
{ | |
switch (i) | |
{ | |
case 0: | |
il.Emit(OpCodes.Ldc_I4_0); | |
break; | |
case 1: | |
il.Emit(OpCodes.Ldc_I4_1); | |
break; | |
case 2: | |
il.Emit(OpCodes.Ldc_I4_2); | |
break; | |
case 3: | |
il.Emit(OpCodes.Ldc_I4_3); | |
break; | |
case 4: | |
il.Emit(OpCodes.Ldc_I4_4); | |
break; | |
case 5: | |
il.Emit(OpCodes.Ldc_I4_5); | |
break; | |
case 6: | |
il.Emit(OpCodes.Ldc_I4_6); | |
break; | |
case 7: | |
il.Emit(OpCodes.Ldc_I4_7); | |
break; | |
case 8: | |
il.Emit(OpCodes.Ldc_I4_8); | |
break; | |
default: | |
if (i < 128) | |
{ | |
il.Emit(OpCodes.Ldc_I4_S, (sbyte)i); | |
} | |
else | |
{ | |
il.Emit(OpCodes.Ldc_I4, i); | |
} | |
break; | |
} | |
} | |
private static void EmitTypeConversion(ILGenerator il, Type type) | |
{ | |
if (type.IsValueType) | |
{ | |
il.Emit(OpCodes.Unbox_Any, type); | |
} | |
else if (type != typeof(object)) | |
{ | |
il.Emit(OpCodes.Castclass, type); | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public interface IActivator | |
{ | |
object Create(params object[] arguments); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment