//------------------------------------------------------------------------------ // 此代码版权(除特别声明或在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 { /// /// Task类型 /// public enum TaskReturnType { /// /// 没有Task /// None, /// /// 仅返回Task /// Task, /// /// 返回Task的值 /// TaskObject } /// /// 表示方法 /// public class Method { private readonly MethodInfo m_info; /// /// 方法执行委托 /// private readonly Func m_invoker; private readonly bool m_isByRef; /// /// 方法 /// /// 方法信息 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); } } /// /// 是否具有返回值 /// public bool HasReturn { get; private set; } /// /// 方法信息 /// public MethodInfo Info => m_info; /// /// 是否有引用类型 /// public bool IsByRef => m_isByRef; /// /// 获取方法名 /// public string Name { get; protected set; } /// /// 返回值类型。 /// 当方法为void或task时,为null /// 当方法为task泛型时,为泛型元素类型 /// public Type ReturnType { get; private set; } /// /// 是否为静态函数 /// public bool Static { get; private set; } /// /// 返回值的Task类型。 /// public TaskReturnType TaskType { get; private set; } /// /// 执行方法。 /// 当方法为void或task时,会返回null /// 当方法为task泛型时,会wait后的值 /// 注意:当调用方为UI主线程时,调用异步方法,则极有可能发生死锁。 /// /// 实例 /// 参数 /// 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; } } /// /// 异步调用 /// /// /// /// 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; } } /// /// 调用异步结果 /// /// /// /// public async Task 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; } } /// /// 生成方法的调用委托 /// /// 方法成员信息 /// /// private Func 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>(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>(bodyCast, instance, parameters).Compile(); } else if (method.ReturnType == typeof(void)) { HasReturn = false; TaskType = TaskReturnType.None; var action = Expression.Lambda>(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>(bodyCast, instance, parameters).Compile(); } } } }