//------------------------------------------------------------------------------ // 此代码版权(除特别声明或在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://touchsocket.net/ // 交流QQ群:234762506 // 感谢您的下载和使用 //------------------------------------------------------------------------------ #if NET6_0_OR_GREATER || NET481_OR_GREATER using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Threading.Tasks; using TouchSocket.Core; namespace TouchSocket.Rpc { /// /// RpcDispatchProxy /// public abstract class RpcDispatchProxy : DispatchProxy where TClient : IRpcClient where TAttribute : RpcAttribute { private readonly ConcurrentDictionary m_methods = new ConcurrentDictionary(); private readonly MethodInfo m_fromResultMethod; /// /// RpcDispatchProxy /// public RpcDispatchProxy() { this.m_fromResultMethod = typeof(Task).GetMethod("FromResult"); } /// /// 获取调用Rpc的客户端。 /// public abstract TClient GetClient(); /// protected sealed override object Invoke(MethodInfo targetMethod, object[] args) { var value = this.m_methods.GetOrAdd(targetMethod, this.AddMethod); var rpcMethod = value.RpcMethod; var invokeKey = value.InvokeKey; var invokeOption = value.InvokeOption ? (IInvokeOption)args.Last() : InvokeOption.WaitInvoke; object[] ps; if (value.InvokeOption) { var pslist = new List(); for (var i = 0; i < args.Length; i++) { if (i < args.Length - 1) { pslist.Add(args[i]); } } ps = pslist.ToArray(); } else { ps = args; } this.OnBefore(targetMethod, value.InvokeKey, ref ps); object result = default; switch (rpcMethod.TaskType) { case TaskReturnType.Task: { this.GetClient().Invoke(invokeKey, invokeOption, ref ps, rpcMethod.ParameterTypes); result = EasyTask.CompletedTask; break; } case TaskReturnType.TaskObject: { var obj = this.GetClient().Invoke(rpcMethod.ReturnType, invokeKey, invokeOption, ref ps, rpcMethod.ParameterTypes); result = value.GenericMethod.Invoke(default, obj); break; } case TaskReturnType.None: default: { if (rpcMethod.HasReturn) { result = this.GetClient().Invoke(rpcMethod.ReturnType, invokeKey, invokeOption, ref ps, rpcMethod.ParameterTypes); } else { this.GetClient().Invoke(invokeKey, invokeOption, ref ps, rpcMethod.ParameterTypes); } break; } } if (rpcMethod.HasByRef) { for (var i = 0; i < ps.Length; i++) { args[i] = ps[i]; } } this.OnAfter(targetMethod, invokeKey, ref args, ref result); return result; } private ProxyModel AddMethod(MethodInfo info) { var attribute = info.GetCustomAttribute(true) ?? throw new Exception($"在方法{info.Name}中没有找到{typeof(TAttribute)}的特性。"); var rpcMethod = new RpcMethod(info); var invokeKey = attribute.GetInvokenKey(rpcMethod); var invokeOption = false; if (info.GetParameters().Length > 0 && typeof(IInvokeOption).IsAssignableFrom(info.GetParameters().Last().ParameterType)) { invokeOption = true; } return new ProxyModel() { InvokeKey = invokeKey, RpcMethod = rpcMethod, InvokeOption = invokeOption, GenericMethod = rpcMethod.TaskType == TaskReturnType.TaskObject ? new Method(this.m_fromResultMethod.MakeGenericMethod(rpcMethod.ReturnType)) : default }; } /// /// 方法调用前 /// /// /// /// /// protected virtual void OnBefore(MethodInfo method, string invokeKey, ref object[] args) { } /// /// 方法调用后 /// /// /// /// /// protected virtual void OnAfter(MethodInfo method, string invokeKey, ref object[] args, ref object result) { } } } #endif