C#RPC公开API方法

时间:2017-01-20 02:02:16

标签: c# unity3d reflection mono

好的,到目前为止,我有办法使用它来公开一些方法:

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#中公开实际的方法,而不是暴露lambdas。

换句话说,我想做这样的事情:

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

}

它可以使用反射找到方法的名称,参数的数量和参数的类型。我很确定这样的事情是可能的,但我有点迷失在这里。不知道如何开始。

1 个答案:

答案 0 :(得分:0)

啊,我明白了。这比我想象的容易......

首先,这个类是必需的:

 recyclerView.setLayoutManager(new LinearLayoutManagerWithSmoothScroller(context));
 recyclerView.smoothScrollToPosition(position);

然后我们需要添加其他类:

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

首先,我们将对象的所有方法传递给Resolve。检查具有Expose属性的任何方法。

如果它在那里,查找参数类型并像以前一样创建一个新命令...在调用实际方法之前,我们将参数转换为该方法所期望的类型。由于我们收到JSON,因此我们无法接收复杂类型,因此我们可以轻松转换大多数参数......也就是说,可能有更好的方法。

最后,如何使用它:

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

添加返回类型也不会更难。