Skip to content

Instantly share code, notes, and snippets.

@RupertAvery
Last active April 13, 2022 01:53
Show Gist options
  • Save RupertAvery/fa4a4a0de29ba8ea1ade070686bde485 to your computer and use it in GitHub Desktop.
Save RupertAvery/fa4a4a0de29ba8ea1ade070686bde485 to your computer and use it in GitHub Desktop.
FastMethodInfo with Generics
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Reflection;
namespace Bite.Runtime.Functions.ForeignInterface
{
public class FastMethodInfo
{
private delegate object ReturnValueDelegate(object instance, object[] arguments);
private delegate void VoidDelegate(object instance, object[] arguments);
private ReturnValueDelegate Delegate { get; }
#region Public
public FastMethodInfo(MethodInfo methodInfo)
{
ParameterExpression instanceExpression = Expression.Parameter(typeof(object), "instance");
ParameterExpression argumentsExpression = Expression.Parameter(typeof(object[]), "arguments");
List<Expression> argumentExpressions = new List<Expression>();
ParameterInfo[] parameterInfos = methodInfo.GetParameters();
for (int i = 0; i < parameterInfos.Length; ++i)
{
ParameterInfo parameterInfo = parameterInfos[i];
argumentExpressions.Add(
Expression.Convert(
Expression.ArrayIndex(argumentsExpression, Expression.Constant(i)),
parameterInfo.ParameterType));
}
MethodCallExpression callExpression = Expression.Call(
!methodInfo.IsStatic ? Expression.Convert(instanceExpression, methodInfo.ReflectedType) : null,
methodInfo,
argumentExpressions);
if (callExpression.Type == typeof(void))
{
VoidDelegate voidDelegate = Expression.Lambda<VoidDelegate>(
callExpression,
instanceExpression,
argumentsExpression).
Compile();
Delegate = (instance, arguments) =>
{
voidDelegate(instance, arguments);
return null;
};
}
else
{
Delegate = Expression.Lambda<ReturnValueDelegate>(
Expression.Convert(callExpression, typeof(object)),
instanceExpression,
argumentsExpression).
Compile();
}
}
public object Invoke(object instance, params object[] arguments)
{
return Delegate(instance, arguments);
}
#endregion
}
public class FastPropertyInfo<T>
{
private delegate object ReturnValueDelegate(T instance, object[] arguments);
private delegate void UpdateValueDelegate(T instance, object value, object[] arguments);
private ReturnValueDelegate GetterDelegate { get; }
private UpdateValueDelegate SetterDelegate { get; }
#region Public
public FastPropertyInfo(PropertyInfo propertyInfo)
{
ParameterExpression instanceExpression = Expression.Parameter(typeof(T), "instance");
ParameterExpression valueExpression = Expression.Parameter(typeof(object), "value");
ParameterExpression argumentsExpression = Expression.Parameter(typeof(object[]), "arguments");
List<Expression> argumentExpressions = new List<Expression>();
ParameterInfo[] parameterInfos = propertyInfo.GetIndexParameters();
for (int i = 0; i < parameterInfos.Length; ++i)
{
ParameterInfo parameterInfo = parameterInfos[i];
argumentExpressions.Add(
Expression.Convert(
Expression.ArrayIndex(argumentsExpression, Expression.Constant(i)),
parameterInfo.ParameterType));
}
IndexExpression callExpression = Expression.Property(
instanceExpression,
propertyInfo,
argumentExpressions);
BinaryExpression assignExpression = Expression.Assign(callExpression, Expression.Convert(valueExpression, propertyInfo.PropertyType));
GetterDelegate = Expression.Lambda<ReturnValueDelegate>(
Expression.Convert(callExpression, typeof(object)),
instanceExpression,
argumentsExpression).
Compile();
SetterDelegate = Expression.Lambda<UpdateValueDelegate>(
assignExpression,
instanceExpression,
valueExpression,
argumentsExpression).
Compile();
}
public object InvokeGet(object instance, params object[] arguments)
{
return GetterDelegate((T)instance, arguments);
}
public void InvokeSet(object instance, object value, params object[] arguments)
{
SetterDelegate((T)instance, value, arguments);
}
#endregion
}
public class FastFieldInfo
{
private delegate object ReturnValueDelegate(object instance);
private ReturnValueDelegate Delegate { get; }
#region Public
public FastFieldInfo(FieldInfo propertyInfo)
{
ParameterExpression instanceExpression = Expression.Parameter(typeof(object), "instance");
MemberExpression callExpression = Expression.Field(!propertyInfo.IsStatic ? Expression.Convert(instanceExpression, propertyInfo.ReflectedType) : null,
propertyInfo);
Delegate = Expression.Lambda<ReturnValueDelegate>(
Expression.Convert(callExpression, typeof(object)),
instanceExpression).
Compile();
}
public object Invoke(object instance)
{
return Delegate(instance);
}
#endregion
}
public class TestClass
{
public int Number { get; set; }
public string String { get; set; }
}
}
var type = typeof(TestClass);
var pi = type.GetProperty("Number");
var fp = new FastPropertyInfo<TestClass>(pi);
var tc = new TestClass();
fp.InvokeSet(tc, 12345, new object[] {} );
Console.WriteLine(tc.Number);
tc.Number = 98765;
var value = fp.InvokeGet(tc, new object[] { });
Console.WriteLine(value);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment