Skip to content

Instantly share code, notes, and snippets.

@usausa
Last active October 3, 2017 09:04
Show Gist options
  • Save usausa/183823e942c79aea80b79033ecc76208 to your computer and use it in GitHub Desktop.
Save usausa/183823e942c79aea80b79033ecc76208 to your computer and use it in GitHub Desktop.
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);
}
}
}
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