ln.types/rpc/RPCContainer.cs

104 lines
3.6 KiB
C#

using System;
using System.Collections.Generic;
using System.Reflection;
namespace ln.types.rpc
{
public class PublishAttribute : Attribute
{
}
public class RPCContainer
{
Dictionary<string, RPCModule> modules = new Dictionary<string, RPCModule>();
public RPCContainer()
{
}
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(moduleName,moduleInstance);
modules.Add(moduleName, rpcModule);
}
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 String Name { get; }
public object ModuleInstance { get; }
public Dictionary<string, MethodInfo> methodInfos = new Dictionary<string, MethodInfo>();
public RPCModule(string moduleName,object instance)
{
Name = moduleName;
ModuleInstance = instance;
Initialize(ModuleInstance.GetType());
}
public RPCModule(string moduleName,Type type)
{
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<PublishAttribute>() != 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[] paramterInfos = methodInfo.GetParameters();
object[] parameters = new object[paramterInfos.Length];
for (int n=0;n<parameters.Length;n++)
{
parameters[n] = Convert.ChangeType(call.Parameters[n], paramterInfos[n].ParameterType);
}
object result = methodInfo.Invoke(ModuleInstance, parameters);
return new RPCResult(call, result);
} catch (Exception e)
{
return new RPCResult(call, e);
}
}
}
}
}