Last active
August 29, 2015 14:21
-
-
Save epetrie/17af2a514e2650ecf43c to your computer and use it in GitHub Desktop.
Reflection / Compiled Lambda Extensions
This file contains 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 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