RaUI/Source/ryControls/Sheng.Winform.Controls/Kernal/FastReflection/MethodInvoker.cs
鑫Intel c3d4ddf574 ### 2021-07-29更新
------
#### MyDbV4   V3.0.2107.2901
- *.[新增]新增支持计算文件MD5。
- *.[新增]部分DataProvider功能移植到DbExtension里,增加扩展性。
- *.[新增]UnixTimeToDateTime和JSTimeToDateTime新增支持long参数。
- *.[合并]合并RyWeb项目到MyDb里。

#### ryControlsV4    V3.0.2107.2901
  -  *.[改进]优化减少大量IDE警告和消息。
2021-07-29 17:09:32 +08:00

115 lines
3.9 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Linq.Expressions;
namespace Sheng.Winform.Controls.Kernal
{
/// <summary>
///
/// </summary>
public interface IMethodInvoker
{
/// <summary>
///
/// </summary>
/// <param name="instance"></param>
/// <param name="parameters"></param>
/// <returns></returns>
object Invoke(object instance, params object[] parameters);
}
/// <summary>
///
/// </summary>
public class MethodInvoker : IMethodInvoker
{
private readonly Func<object, object[], object> m_invoker;
/// <summary>
///
/// </summary>
public MethodInfo MethodInfo { get; private set; }
/// <summary>
///
/// </summary>
/// <param name="methodInfo"></param>
public MethodInvoker(MethodInfo methodInfo)
{
this.MethodInfo = methodInfo;
this.m_invoker = CreateInvokeDelegate(methodInfo);
}
/// <summary>
///
/// </summary>
/// <param name="instance"></param>
/// <param name="parameters"></param>
/// <returns></returns>
public object Invoke(object instance, params object[] parameters)
{
return this.m_invoker(instance, parameters);
}
private static Func<object, object[], object> CreateInvokeDelegate(MethodInfo methodInfo)
{
// Target: ((TInstance)instance).Method((T0)parameters[0], (T1)parameters[1], ...)
// parameters to execute
var instanceParameter = Expression.Parameter(typeof(object), "instance");
var parametersParameter = Expression.Parameter(typeof(object[]), "parameters");
// build parameter list
var parameterExpressions = new List<Expression>();
var paramInfos = methodInfo.GetParameters();
for (int i = 0; i < paramInfos.Length; i++)
{
// (Ti)parameters[i]
BinaryExpression valueObj = Expression.ArrayIndex(
parametersParameter, Expression.Constant(i));
UnaryExpression valueCast = Expression.Convert(
valueObj, paramInfos[i].ParameterType);
parameterExpressions.Add(valueCast);
}
// non-instance for static method, or ((TInstance)instance)
var instanceCast = methodInfo.IsStatic ? null :
Expression.Convert(instanceParameter, methodInfo.ReflectedType);
// static invoke or ((TInstance)instance).Method
var methodCall = Expression.Call(instanceCast, methodInfo, parameterExpressions);
// ((TInstance)instance).Method((T0)parameters[0], (T1)parameters[1], ...)
if (methodCall.Type == typeof(void))
{
var lambda = Expression.Lambda<Action<object, object[]>>(
methodCall, instanceParameter, parametersParameter);
Action<object, object[]> execute = lambda.Compile();
return (instance, parameters) =>
{
execute(instance, parameters);
return null;
};
}
else
{
var castMethodCall = Expression.Convert(methodCall, typeof(object));
var lambda =Expression.Lambda<Func<object, object[], object>>(
castMethodCall, instanceParameter, parametersParameter);
return lambda.Compile();
}
}
#region IMethodInvoker Members
object IMethodInvoker.Invoke(object instance, params object[] parameters)
{
return this.Invoke(instance, parameters);
}
#endregion
}
}