104 lines
3.6 KiB
C#
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);
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|