Skip to content

Instantly share code, notes, and snippets.

@epetrie
Last active August 29, 2015 14:21
Show Gist options
  • Save epetrie/17af2a514e2650ecf43c to your computer and use it in GitHub Desktop.
Save epetrie/17af2a514e2650ecf43c to your computer and use it in GitHub Desktop.
Reflection / Compiled Lambda Extensions
public static class Reflection
{
public static ConstructorInfo GetDefaultConstructor(this Type type)
{
return type.GetConstructor(Type.EmptyTypes);
}
public static T CreateInstance<T>(this Type type, params object[] args) where T : class
{
return CreateInstance(type, args) as T;
}
public static object CreateInstance(this Type type, params object[] args)
{
return Activate(type, args);
}
public static T OrNew<T>(this T obj, Func<object[], T> activator = null, params object[] args) where T : class
{
if (obj.Equals(null))
return activator == null ? Activate<T>(args) : activator(args);
return obj;
}
#region Compiled Lambda Stuff
// this is much faster than Activator.CreateInstance especially when no parameterless ctor exists
private static T Activate<T>(params object[] args) where T : class
{
return Activate<T>(typeof(T), args);
}
private static T Activate<T>(Type type, params object[] args) where T : class
{
return Activate(type, args) as T;
}
private static object Activate(Type type, params object[] args)
{
var ctor = args == null ? type.GetDefaultConstructor() : type.GetConstructor(args.Select(o => o.GetType()).ToArray());
return ctor == null ? null : GetActivator(ctor)(args);
}
private static Func<object[], object> GetActivator(ConstructorInfo ctor)
{
var paramsInfo = ctor.GetParameters();
//create a single param of type object[]
var param = Expression.Parameter(typeof(object[]), "args");
var 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++)
{
var index = Expression.Constant(i);
var paramType = paramsInfo[i].ParameterType;
var paramAccessorExp = Expression.ArrayIndex(param, index);
var paramCastExp = Expression.Convert(paramAccessorExp, paramType);
argsExp[i] = paramCastExp;
}
//make a NewExpression that calls the
//ctor with the args we just created
var newExp = Expression.New(ctor, argsExp);
//create a lambda with the New
//Expression as body and our param object[] as arg
var lambda = Expression.Lambda<Func<object[], object>>(newExp, param);
//compile it
return lambda.Compile();
}
#endregion
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment