[英]C# RPC expose API methods
好的,到目前为止,我有办法使用这个公开一些方法:
AddCommand ("UpdateStar", ((args) => {
// do something
}));
它将命令添加到SortedDictionary<string, SimpleDelegate>
。 这是我的SimpleDelegate
定义:
public delegate void SimpleDelegate(JSONNode args);
它非常简单,从Javascript我发送一个参数列表,在C#中我收到一个JSONNode
,这是一个JSONArray
。 它正在工作,但做这样的事情非常烦人:
string name = args[0].Value;
int x = args[1].AsInt;
...
最后,我想做的是在C#中公开实际的方法而不是暴露lambda。
换句话说,我想做这样的事情:
[expose-to-rpc]
public void AddSystem(string name, int x, int y) {
}
它可以使用反射找到方法的名称,参数的数量和参数的类型。 我很确定这样的事情是可能的,但我有点迷失在这里。 不知道如何开始。
啊,我明白了。 这比我想象的容易......
首先,这个类是必需的:
[AttributeUsage(AttributeTargets.Method)]
public class ExposeAttribute: Attribute {
}
然后我们需要添加其他类:
public static class RPCApi
{
public static object nodeToType(JSONNode node, Type type) {
if (typeof(int) == type) {
return node.AsInt;
}
if (typeof(long) == type) {
return node.AsLong;
}
if (typeof(bool) == type) {
return node.AsBool;
}
if (typeof(string) == type) {
return node.Value;
}
if (typeof(float) == type) {
return node.AsFloat;
}
if (typeof(double) == type) {
return node.AsDouble;
}
if (typeof(JSONArray) == type) {
return node.AsArray;
}
if (typeof(JSONClass) == type) {
return node.AsObject;
}
return null;
}
public static void Resolve(MonoBehaviour behaviour) {
NetworkManager manager = behaviour.GetComponent<NetworkManager> ();
Type t = behaviour.GetType ();
MethodInfo[] methods = t.GetMethods ();
for (int i = 0; i < methods.Length; i++) {
MethodInfo meth = methods [i];
ExposeAttribute[] atts = (ExposeAttribute[])meth.GetCustomAttributes (typeof(ExposeAttribute), true);
if (atts.Length == 0) {
continue;
}
ParameterInfo[] paramss = meth.GetParameters ();
manager.AddCommand (meth.Name, ((args) => {
object[] argss = new object[paramss.Length];
for(int l=0; l<argss.Length; l++) {
argss[l] = nodeToType(
args[l],
paramss[l].ParameterType
);
}
meth.Invoke(behaviour, argss);
}));
}
}
}
首先,我们将对象的所有方法传递给Resolve。 检查具有Expose属性的任何方法。
如果它在那里,查找参数类型并像以前一样创建一个新命令...在调用实际方法之前,我们将参数转换为该方法所期望的类型。 由于我们收到JSON,因此我们无法接收复杂类型,因此我们可以轻松转换大多数参数......也就是说,可能有更好的方法。
最后,如何使用它:
public class NetworkManager : MonoBehaviour {
public void Start () {
RPCApi.Resolve (this);
}
...
[Expose]
public void addStar(string system) {
Planet fun = JsonUtility.FromJson<Planet> (system);
GameObject prefabs = GameObject.Find ("PrefabContainer");
PrefabContainer obj = prefabs.GetComponent<PrefabContainer> ();
GameObject newobj = Instantiate (obj.star, new Vector3 (fun.x, fun.y, 0), Quaternion.Euler (0, 0, 0));
newobj.name = fun.id;
newobj.GetComponent<PlanetBehaviour> ().planetConfig = fun;
}
[Expose]
public void UpdateStar (string uuid, float x, float y) {
GameObject system = GameObject.Find (uuid);
MoveToBehaviour move = system.GetComponent<MoveToBehaviour>();
move.MoveTo(new Vector3(x, y, 0));
}
}
添加返回类型也不应该困难得多。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.