繁体   English   中英

C#RPC公开API方法

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM