简体   繁体   English

C#RPC公开API方法

[英]C# RPC expose API methods

Ok, so far, I have a way to expose some methods using this: 好的,到目前为止,我有办法使用这个公开一些方法:

AddCommand ("UpdateStar", ((args) => {
   // do something
}));

It adds the command into a SortedDictionary<string, SimpleDelegate> . 它将命令添加到SortedDictionary<string, SimpleDelegate> Here's my SimpleDelegate definition: 这是我的SimpleDelegate定义:

public delegate void SimpleDelegate(JSONNode args);

It's pretty straight forward, from Javascript I send a list of argument and in C# I receive a JSONNode which is a JSONArray . 它非常简单,从Javascript我发送一个参数列表,在C#中我收到一个JSONNode ,这是一个JSONArray It's working but it's quite annoying to do things such as: 它正在工作,但做这样的事情非常烦人:

string name = args[0].Value;
int x = args[1].AsInt;
...

In the end, what I'd like to do is to instead expose actual methods in C# instead of exposing lambdas. 最后,我想做的是在C#中公开实际的方法而不是暴露lambda。

In other words, I'd like to do something like this: 换句话说,我想做这样的事情:

[expose-to-rpc]
public void AddSystem(string name, int x, int y) {

}

It could find the name of the method, the number of argument and the type of arguments using reflection. 它可以使用反射找到方法的名称,参数的数量和参数的类型。 I'm pretty sure something like that is possible but I'm kind of lost here. 我很确定这样的事情是可能的,但我有点迷失在这里。 Not sure how to get started. 不知道如何开始。

Ah I got it. 啊,我明白了。 It was easier than I thought... 这比我想象的容易......

First, this class is required: 首先,这个类是必需的:

[AttributeUsage(AttributeTargets.Method)]
public class ExposeAttribute: Attribute {
}

Then we need to add this other class: 然后我们需要添加其他类:

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);
            }));
        }
    }
}

First we get all the methods of the object passed to Resolve. 首先,我们将对象的所有方法传递给Resolve。 Check for any method with the attribute Expose. 检查具有Expose属性的任何方法。

If it's there, lookup the parameters type and create a new command as I was doing before... Thought before calling the actual method, we convert the arguments to the type that the method is expecting. 如果它在那里,查找参数类型并像以前一样创建一个新命令...在调用实际方法之前,我们将参数转换为该方法所期望的类型。 Since we receive JSON, We cannot receive complex types so we can convert most parameters easily... That said, there might be a better way to that. 由于我们收到JSON,因此我们无法接收复杂类型,因此我们可以轻松转换大多数参数......也就是说,可能有更好的方法。

Finally, how to use it: 最后,如何使用它:

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));
    }
}

Adding the return type shouldn't be much harder either. 添加返回类型也不应该困难得多。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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