using System; using System.Collections.Generic; using System.Reflection; using System.Linq; namespace ln.type.rpc { public class PublishAttribute : Attribute { } public class RPCContainer { Dictionary modules = new Dictionary(); Func checkAccessHook; public RPCContainer() { } public RPCContainer(Func checkAccessHook) { this.checkAccessHook = checkAccessHook; } public void Add(object moduleInstance) => Add(moduleInstance.GetType().Name, moduleInstance); public void Add(string moduleName,object moduleInstance) { if (modules.ContainsKey(moduleName)) throw new ArgumentOutOfRangeException(nameof(moduleName), "Module with same name already added"); RPCModule rpcModule = new RPCModule(this,moduleName,moduleInstance); modules.Add(moduleName, rpcModule); } public void Remove(string moduleName) { modules.Remove(moduleName); } public void Remove(object moduleInstance) { foreach (RPCModule module in modules.Values) { if (module.ModuleInstance == moduleInstance) { modules.Remove(module.Name); return; } } } public RPCResult Invoke(RPCCall call) { if ((call.ModuleName != null) && !modules.ContainsKey(call.ModuleName)) throw new KeyNotFoundException(call.ModuleName); RPCModule rpcModule = call.ModuleName != null ? modules[call.ModuleName] : modules[""]; return rpcModule.Invoke(call); } public class RPCModule { public RPCContainer Container { get; } public String Name { get; } public object ModuleInstance { get; } public Dictionary methodInfos = new Dictionary(); public RPCModule(RPCContainer container,string moduleName,object instance) { Container = container; Name = moduleName; ModuleInstance = instance; Initialize(ModuleInstance.GetType()); } public RPCModule(RPCContainer container,string moduleName,Type type) { Container = container; Name = moduleName; ModuleInstance = null; Initialize(type); } private void Initialize(Type type) { foreach (MethodInfo methodInfo in type.GetMethods(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance)) { if (methodInfo.IsStatic || !Object.ReferenceEquals(ModuleInstance,null) ) { if (methodInfo.IsPublic || (methodInfo.GetCustomAttribute() != null)) { methodInfos.Add(methodInfo.Name, methodInfo); } } } } public RPCResult Invoke(RPCCall call) { if (!Name.Equals(call.ModuleName) && (call.ModuleName != null)) throw new ArgumentOutOfRangeException(nameof(call.ModuleName), "RPC: Invoke called for wrong module"); try { if (!methodInfos.ContainsKey(call.MethodName)) throw new KeyNotFoundException(call.MethodName); MethodInfo methodInfo = methodInfos[call.MethodName]; ParameterInfo[] parameterInfos = methodInfo.GetParameters(); object[] parameters = new object[parameterInfos.Length]; for (int n = 0; n < parameters.Length; n++) { Type pType = parameterInfos[n].ParameterType; if (pType.Equals(typeof(Guid))) { parameters[n] = Guid.Parse(call.Parameters[n].ToString()); } else if (pType.IsArray) { Type eType = pType.GetElementType(); object[] src = (object[])call.Parameters[n]; Array a = Array.CreateInstance(eType, src.Length); for (int m=0;m