Skip to content

Instantly share code, notes, and snippets.

@valerysntx
Created December 17, 2015 08:53
Show Gist options
  • Save valerysntx/eb1b3ac87cd2ac381934 to your computer and use it in GitHub Desktop.
Save valerysntx/eb1b3ac87cd2ac381934 to your computer and use it in GitHub Desktop.
Object Activator / Build Instance Factory Delegate
using System;
using System.Reflection;
using System.Linq.Expressions;
using System.Collections;
using System.Linq;
public class Program
{
public static void Main()
{
var factory = ActivatorEx.CreateInstanceFactoryDelegate<Hello>();
factory("hello", 777);
typeof(Hello).CreateFactory<Hello>().Invoke("hello",888);
}
}
public class Hello
{
public Hello(string greetMessage, int age)
{
Console.WriteLine(greetMessage + age.ToString());
}
}
public static class ActivatorEx
{
public delegate T ObjectActivator<T>(params object[] args);
public static ObjectActivator<T> GetActivator<T>(ConstructorInfo ctor)
{
Type type = ctor.DeclaringType;
ParameterInfo[] paramsInfo = ctor.GetParameters();
//create a single param of type object[]
ParameterExpression param = Expression.Parameter(typeof (object[]), "args");
Expression[] argsExp = new Expression[paramsInfo.Length];
//pick each arg from the params array
//and create a typed expression of them
for (int i = 0; i < paramsInfo.Length; i++)
{
Expression index = Expression.Constant(i);
Type paramType = paramsInfo[i].ParameterType;
Expression paramAccessorExp = Expression.ArrayIndex(param, index);
Expression paramCastExp = Expression.Convert(paramAccessorExp, paramType);
argsExp[i] = paramCastExp;
}
//make a NewExpression that calls the
//ctor with the args we just created
NewExpression newExp = Expression.New(ctor, argsExp);
//create a lambda with the New
//Expression as body and our param object[] as arg
LambdaExpression lambda = Expression.Lambda(typeof (ObjectActivator<T>), newExp, param);
//compile it
ObjectActivator<T> compiled = (ObjectActivator<T>)lambda.Compile();
return compiled;
}
public static ObjectActivator<T> CreateInstanceFactoryDelegate<T>()
{
ConstructorInfo ctor = typeof (T).GetConstructors().First();
ObjectActivator<T> createdActivator = GetActivator<T>(ctor);
return createdActivator;
}
public static ObjectActivator<T> CreateFactory<T>(this Type t){
return CreateInstanceFactoryDelegate<T>();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment