2017-01-20 4 views
1

を公開し、これまでのところ、私はこれを使用して、いくつかのメソッドを公開する方法があります。C#のRPC [OK]をAPIメソッド

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

それはSortedDictionary<string, SimpleDelegate>にコマンドを追加します。

public delegate void SimpleDelegate(JSONNode args); 

それはJavascriptから私は、引数のリストを送信し、C#で、私はJSONArrayあるJSONNodeを受け、かなりまっすぐ進むです: はここに私のSimpleDelegate定義です。それは働いているが、それはのようなものを行うには非常に迷惑です:最後に

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

を、私は何をしたいのは、代わりにC#での実際のメソッドの代わりにさらすラムダを公開することです。

言い換えれば、私はこのような何かをしたいと思います:

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

} 

それはメソッドは、引数の数と反射を使用して、引数の型の名前を見つけることができます。私はそれが可能なようなことはかなり確信していますが、私はここで紛失しています。どのように開始するか分からない。

+1

[特定のカスタム属性を持つすべてのメソッドを呼び出すためにリフレクションを使用するにはどうすればよいですか?](http://stackoverflow.com/questions/2831809/how-would-i-use-reflection-to- –

+0

@KeithNicholas私は自分の答えを解決しましたが、メソッドを取得するよりも少し複雑です。パラメータを解析して型を返し、次に変換されたパラメータで実際のメソッドを呼び出す必要があります。 –

+0

ええ、それはかなりまっすぐです、あなたはあなたの質問に応じて始めるために何かを必要としました、それのすべては既にSOで繰り返し尋ねられています:) –

答えて

0

ああ私はそれを得た。その後、我々は、この他のクラスを追加する必要が

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

をはるかに困難のいずれかであってはならない戻り値の型を追加。

関連する問題