Skip to content

Instantly share code, notes, and snippets.

@jasmin-mistry
Last active January 12, 2020 13:30
Show Gist options
  • Save jasmin-mistry/6e0684c3009cddeda706d2ebe72a302e to your computer and use it in GitHub Desktop.
Save jasmin-mistry/6e0684c3009cddeda706d2ebe72a302e to your computer and use it in GitHub Desktop.
Invoke generic method dynamically at runtime
public static class ActivatorExt
{
private static ObjectActivator<T> GetActivator<T>(ConstructorInfo ctor)
{
var paramsInfo = ctor.GetParameters();
var param = Expression.Parameter(typeof(object[]), "args");
var argsExp = new Expression[paramsInfo.Length];
for (var i = 0; i < paramsInfo.Length; i++)
{
Expression index = Expression.Constant(i);
var paramType = paramsInfo[i].ParameterType;
Expression paramAccessorExp = Expression.ArrayIndex(param, index);
Expression paramCastExp = Expression.Convert(paramAccessorExp, paramType);
argsExp[i] = paramCastExp;
}
var newExp = Expression.New(ctor, argsExp);
var lambda = Expression.Lambda(typeof(ObjectActivator<T>), newExp, param);
var compiled = (ObjectActivator<T>) lambda.Compile();
return compiled;
}
public static T CreateInstance<T>(params object[] args)
{
var ctor = typeof(T).GetConstructors().First();
var createdActivator = GetActivator<T>(ctor);
return createdActivator(args);
}
private delegate T ObjectActivator<out T>(params object[] args);
}
public static class MyType
{
private static object InvokeGenericGetError(Type genericType, params object[] args)
{
var genericMethod = typeof(MyType).GetGenericMethod(nameof(GetMyType), new[] {genericType});
var result = genericMethod.Invoke(null, new object[] {args});
return result;
}
public static object GetMyType(Type myType, params object[] args)
{
if (myType == null) throw new ArgumentNullException(nameof(myType));
return InvokeGenericGetError(myType, args);
}
public static T GetMyType<T>(object[] args) //where T : TestClass
{
return ActivatorExt.CreateInstance<T>(args);
}
}
void Main()
{
var obj = MyType.GetMyType(typeof(TestClass), "hello", 1234) as TestClass;
obj.Dump();
var obj1 = MyType.GetMyType<TestClass>(new object[] {"7 ate 9", 789}) as TestClass;
obj1.Dump();
}
public class TestClass
{
public TestClass(string text, int id)
{
Id = id;
Text = text;
}
public int Id {get; set;}
public string Text {get; set;}
}
public static class TypeExtension
{
public static MethodInfo GetGenericMethod(this Type t, string name, Type[] genericArgTypes)
{
var methods = t.GetMethods(BindingFlags.Public | BindingFlags.Static);
var method = methods.FirstOrDefault(m => m.Name == name && m.IsGenericMethod);
var genericMethod = method?.MakeGenericMethod(genericArgTypes);
return genericMethod;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment