public static List <(string, RpcFunctionDelegate)> ReflectRpcFunctions(this IRpc rpcHost) { var hostType = rpcHost.GetType(); var methods = hostType.GetMethods(); var tupple = new List <(string, RpcFunctionDelegate)>(); foreach (var method in methods) { var hookAttributes = method.GetCustomAttributes(typeof(RpcAttribute), false); if (hookAttributes.Length == 1) { var rpcAttribute = (RpcAttribute)hookAttributes[0]; RpcFunctionDelegate rpcFunction = async(context) => { var pas = BindParamters(method, context); object result = null; object host = null; if (!method.IsStatic) { host = rpcHost; } if (method.ReturnType == typeof(Task)) { Task awaitable = (Task)method.Invoke(host, pas); await awaitable; } else if (method.ReturnType == typeof(void)) { method.Invoke(host, pas); } else if (method.ReturnType.IsGenericType) { if (method.ReturnType.GetGenericTypeDefinition() == typeof(Task <>)) { result = await method.InvokeAsync(host, pas); } else { result = method.Invoke(host, pas); } } else { result = method.Invoke(host, pas); } var encodedObject = PointerOrLocalIdEncoder.Instance.Encode(result); var resultWrapper = new Dictionary <string, object>() { { "results", encodedObject } }; if (context is StorageRpcContext storageRpcContext) { storageRpcContext.Response.MetaText = Json.Encode(resultWrapper); } }; var hostName = rpcHost.ReflectRpcHostName(); var methodName = rpcAttribute.Name ?? method.Name; var rpcMethodName = $"{hostName}_{methodName}"; if (!method.IsStatic) { var hostId = rpcHost.ReflectRpcHostIdPropertyValue(); rpcMethodName = $"{hostName}_{hostId}_{methodName}"; } var mixedResult = (rpcMethodName, rpcFunction); tupple.Add(mixedResult); } } return(tupple); }