You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
360 lines
13 KiB
360 lines
13 KiB
|
3 months ago
|
//------------------------------------------------------------------------------
|
||
|
|
// 此代码版权(除特别声明或在XREF结尾的命名空间的代码)归作者本人若汝棋茗所有
|
||
|
|
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
|
||
|
|
// CSDN博客:https://blog.csdn.net/qq_40374647
|
||
|
|
// 哔哩哔哩视频:https://space.bilibili.com/94253567
|
||
|
|
// Gitee源代码仓库:https://gitee.com/RRQM_Home
|
||
|
|
// Github源代码仓库:https://github.com/RRQM
|
||
|
|
// API首页:https://www.yuque.com/rrqm/touchsocket/index
|
||
|
|
// 交流QQ群:234762506
|
||
|
|
// 感谢您的下载和使用
|
||
|
|
//------------------------------------------------------------------------------
|
||
|
|
//------------------------------------------------------------------------------
|
||
|
|
using System;
|
||
|
|
using System.Linq;
|
||
|
|
using System.Linq.Expressions;
|
||
|
|
using System.Reflection;
|
||
|
|
using System.Threading.Tasks;
|
||
|
|
|
||
|
|
namespace TouchSocket.Core
|
||
|
|
{
|
||
|
|
/// <summary>
|
||
|
|
/// Task类型
|
||
|
|
/// </summary>
|
||
|
|
public enum TaskReturnType
|
||
|
|
{
|
||
|
|
/// <summary>
|
||
|
|
/// 没有Task
|
||
|
|
/// </summary>
|
||
|
|
None,
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 仅返回Task
|
||
|
|
/// </summary>
|
||
|
|
Task,
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 返回Task的值
|
||
|
|
/// </summary>
|
||
|
|
TaskObject
|
||
|
|
}
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 表示方法
|
||
|
|
/// </summary>
|
||
|
|
public class Method
|
||
|
|
{
|
||
|
|
private readonly MethodInfo m_info;
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 方法执行委托
|
||
|
|
/// </summary>
|
||
|
|
private readonly Func<object, object[], object> m_invoker;
|
||
|
|
|
||
|
|
private readonly bool m_isByRef;
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 方法
|
||
|
|
/// </summary>
|
||
|
|
/// <param name="method">方法信息</param>
|
||
|
|
public Method(MethodInfo method)
|
||
|
|
{
|
||
|
|
m_info = method ?? throw new ArgumentNullException(nameof(method));
|
||
|
|
Name = method.Name;
|
||
|
|
Static = method.IsStatic;
|
||
|
|
foreach (var item in method.GetParameters())
|
||
|
|
{
|
||
|
|
if (item.ParameterType.IsByRef)
|
||
|
|
{
|
||
|
|
m_isByRef = true;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if (this.m_isByRef||GlobalEnvironment.OptimizedPlatforms.HasFlag(OptimizedPlatforms.Unity))
|
||
|
|
{
|
||
|
|
if (method.ReturnType == typeof(Task))
|
||
|
|
{
|
||
|
|
HasReturn = false;
|
||
|
|
TaskType = TaskReturnType.Task;
|
||
|
|
}
|
||
|
|
else if (method.ReturnType.IsGenericType && method.ReturnType.GetGenericTypeDefinition() == typeof(Task<>))
|
||
|
|
{
|
||
|
|
HasReturn = true;
|
||
|
|
ReturnType = method.ReturnType.GetGenericArguments()[0];
|
||
|
|
TaskType = TaskReturnType.TaskObject;
|
||
|
|
}
|
||
|
|
else if (method.ReturnType == typeof(void))
|
||
|
|
{
|
||
|
|
HasReturn = false;
|
||
|
|
TaskType = TaskReturnType.None;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
HasReturn = true;
|
||
|
|
TaskType = TaskReturnType.None;
|
||
|
|
ReturnType = method.ReturnType;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
m_invoker = CreateInvoker(method);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 是否具有返回值
|
||
|
|
/// </summary>
|
||
|
|
public bool HasReturn { get; private set; }
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 方法信息
|
||
|
|
/// </summary>
|
||
|
|
public MethodInfo Info => m_info;
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 是否有引用类型
|
||
|
|
/// </summary>
|
||
|
|
public bool IsByRef => m_isByRef;
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 获取方法名
|
||
|
|
/// </summary>
|
||
|
|
public string Name { get; protected set; }
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 返回值类型。
|
||
|
|
/// <para>当方法为void或task时,为null</para>
|
||
|
|
/// <para>当方法为task泛型时,为泛型元素类型</para>
|
||
|
|
/// </summary>
|
||
|
|
public Type ReturnType { get; private set; }
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 是否为静态函数
|
||
|
|
/// </summary>
|
||
|
|
public bool Static { get; private set; }
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 返回值的Task类型。
|
||
|
|
/// </summary>
|
||
|
|
public TaskReturnType TaskType { get; private set; }
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 执行方法。
|
||
|
|
/// <para>当方法为void或task时,会返回null</para>
|
||
|
|
/// <para>当方法为task泛型时,会wait后的值</para>
|
||
|
|
/// <para>注意:当调用方为UI主线程时,调用异步方法,则极有可能发生死锁。</para>
|
||
|
|
/// </summary>
|
||
|
|
/// <param name="instance">实例</param>
|
||
|
|
/// <param name="parameters">参数</param>
|
||
|
|
/// <returns></returns>
|
||
|
|
public object Invoke(object instance, params object[] parameters)
|
||
|
|
{
|
||
|
|
switch (TaskType)
|
||
|
|
{
|
||
|
|
case TaskReturnType.None:
|
||
|
|
{
|
||
|
|
object re;
|
||
|
|
if (m_isByRef || GlobalEnvironment.OptimizedPlatforms.HasFlag(OptimizedPlatforms.Unity))
|
||
|
|
{
|
||
|
|
re = m_info.Invoke(instance, parameters);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
re = m_invoker.Invoke(instance, parameters);
|
||
|
|
}
|
||
|
|
return re;
|
||
|
|
}
|
||
|
|
case TaskReturnType.Task:
|
||
|
|
{
|
||
|
|
object re;
|
||
|
|
if (m_isByRef || GlobalEnvironment.OptimizedPlatforms.HasFlag(OptimizedPlatforms.Unity))
|
||
|
|
{
|
||
|
|
re = m_info.Invoke(instance, parameters);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
re = m_invoker.Invoke(instance, parameters);
|
||
|
|
}
|
||
|
|
Task task = (Task)re;
|
||
|
|
task.Wait();
|
||
|
|
return default;
|
||
|
|
}
|
||
|
|
case TaskReturnType.TaskObject:
|
||
|
|
{
|
||
|
|
object re;
|
||
|
|
if (m_isByRef || GlobalEnvironment.OptimizedPlatforms.HasFlag(OptimizedPlatforms.Unity))
|
||
|
|
{
|
||
|
|
re = m_info.Invoke(instance, parameters);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
re = m_invoker.Invoke(instance, parameters);
|
||
|
|
}
|
||
|
|
Task task = (Task)re;
|
||
|
|
task.Wait();
|
||
|
|
return task.GetType().GetProperty("Result").GetValue(task);
|
||
|
|
}
|
||
|
|
default:
|
||
|
|
return default;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 异步调用
|
||
|
|
/// </summary>
|
||
|
|
/// <param name="instance"></param>
|
||
|
|
/// <param name="parameters"></param>
|
||
|
|
/// <returns></returns>
|
||
|
|
public Task InvokeAsync(object instance, params object[] parameters)
|
||
|
|
{
|
||
|
|
switch (TaskType)
|
||
|
|
{
|
||
|
|
case TaskReturnType.None:
|
||
|
|
{
|
||
|
|
throw new Exception("该方法不包含Task。");
|
||
|
|
}
|
||
|
|
case TaskReturnType.Task:
|
||
|
|
{
|
||
|
|
object re;
|
||
|
|
if (m_isByRef || GlobalEnvironment.OptimizedPlatforms.HasFlag(OptimizedPlatforms.Unity))
|
||
|
|
{
|
||
|
|
re = m_info.Invoke(instance, parameters);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
re = m_invoker.Invoke(instance, parameters);
|
||
|
|
}
|
||
|
|
return (Task)re;
|
||
|
|
}
|
||
|
|
case TaskReturnType.TaskObject:
|
||
|
|
{
|
||
|
|
object re;
|
||
|
|
if (m_isByRef || GlobalEnvironment.OptimizedPlatforms.HasFlag(OptimizedPlatforms.Unity))
|
||
|
|
{
|
||
|
|
re = m_info.Invoke(instance, parameters);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
re = m_invoker.Invoke(instance, parameters);
|
||
|
|
}
|
||
|
|
return (Task)re;
|
||
|
|
}
|
||
|
|
default:
|
||
|
|
return default;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 调用异步结果
|
||
|
|
/// </summary>
|
||
|
|
/// <param name="instance"></param>
|
||
|
|
/// <param name="parameters"></param>
|
||
|
|
/// <returns></returns>
|
||
|
|
public async Task<object> InvokeObjectAsync(object instance, params object[] parameters)
|
||
|
|
{
|
||
|
|
switch (TaskType)
|
||
|
|
{
|
||
|
|
case TaskReturnType.None:
|
||
|
|
{
|
||
|
|
object re;
|
||
|
|
if (m_isByRef || GlobalEnvironment.OptimizedPlatforms.HasFlag(OptimizedPlatforms.Unity))
|
||
|
|
{
|
||
|
|
re = m_info.Invoke(instance, parameters);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
re = m_invoker.Invoke(instance, parameters);
|
||
|
|
}
|
||
|
|
return re;
|
||
|
|
}
|
||
|
|
case TaskReturnType.Task:
|
||
|
|
{
|
||
|
|
object re;
|
||
|
|
if (m_isByRef || GlobalEnvironment.OptimizedPlatforms.HasFlag(OptimizedPlatforms.Unity))
|
||
|
|
{
|
||
|
|
re = m_info.Invoke(instance, parameters);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
re = m_invoker.Invoke(instance, parameters);
|
||
|
|
}
|
||
|
|
Task task = (Task)re;
|
||
|
|
await task;
|
||
|
|
return default;
|
||
|
|
}
|
||
|
|
case TaskReturnType.TaskObject:
|
||
|
|
{
|
||
|
|
object re;
|
||
|
|
if (m_isByRef || GlobalEnvironment.OptimizedPlatforms.HasFlag(OptimizedPlatforms.Unity))
|
||
|
|
{
|
||
|
|
re = m_info.Invoke(instance, parameters);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
re = m_invoker.Invoke(instance, parameters);
|
||
|
|
}
|
||
|
|
Task task = (Task)re;
|
||
|
|
await task;
|
||
|
|
return task.GetType().GetProperty("Result").GetValue(task);
|
||
|
|
}
|
||
|
|
default:
|
||
|
|
return default;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 生成方法的调用委托
|
||
|
|
/// </summary>
|
||
|
|
/// <param name="method">方法成员信息</param>
|
||
|
|
/// <exception cref="ArgumentException"></exception>
|
||
|
|
/// <returns></returns>
|
||
|
|
private Func<object, object[], object> CreateInvoker(MethodInfo method)
|
||
|
|
{
|
||
|
|
var instance = Expression.Parameter(typeof(object), "instance");
|
||
|
|
var parameters = Expression.Parameter(typeof(object[]), "parameters");
|
||
|
|
|
||
|
|
var instanceCast = method.IsStatic ? null : Expression.Convert(instance, method.DeclaringType);
|
||
|
|
var parametersCast = method.GetParameters().Select((p, i) =>
|
||
|
|
{
|
||
|
|
var parameter = Expression.ArrayIndex(parameters, Expression.Constant(i));
|
||
|
|
return Expression.Convert(parameter, p.ParameterType);
|
||
|
|
});
|
||
|
|
|
||
|
|
var body = Expression.Call(instanceCast, method, parametersCast);
|
||
|
|
|
||
|
|
if (method.ReturnType == typeof(Task))
|
||
|
|
{
|
||
|
|
HasReturn = false;
|
||
|
|
TaskType = TaskReturnType.Task;
|
||
|
|
var bodyCast = Expression.Convert(body, typeof(object));
|
||
|
|
return Expression.Lambda<Func<object, object[], object>>(bodyCast, instance, parameters).Compile();
|
||
|
|
}
|
||
|
|
else if (method.ReturnType.IsGenericType && method.ReturnType.GetGenericTypeDefinition() == typeof(Task<>))
|
||
|
|
{
|
||
|
|
TaskType = TaskReturnType.TaskObject;
|
||
|
|
HasReturn = true;
|
||
|
|
ReturnType = method.ReturnType.GetGenericArguments()[0];
|
||
|
|
var bodyCast = Expression.Convert(body, typeof(object));
|
||
|
|
return Expression.Lambda<Func<object, object[], object>>(bodyCast, instance, parameters).Compile();
|
||
|
|
}
|
||
|
|
else if (method.ReturnType == typeof(void))
|
||
|
|
{
|
||
|
|
HasReturn = false;
|
||
|
|
TaskType = TaskReturnType.None;
|
||
|
|
var action = Expression.Lambda<Action<object, object[]>>(body, instance, parameters).Compile();
|
||
|
|
return (_instance, _parameters) =>
|
||
|
|
{
|
||
|
|
action.Invoke(_instance, _parameters);
|
||
|
|
return null;
|
||
|
|
};
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
HasReturn = true;
|
||
|
|
TaskType = TaskReturnType.None;
|
||
|
|
ReturnType = method.ReturnType;
|
||
|
|
var bodyCast = Expression.Convert(body, typeof(object));
|
||
|
|
return Expression.Lambda<Func<object, object[], object>>(bodyCast, instance, parameters).Compile();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|