0

プロジェクト管理ソリューションであるAsanaの C# で API ラッパーを設計しています。設計プロセス中に、いくつかの障害に遭遇しました。API ラッパーを設計する良い方法は何でしょうか。

私が統合している Asana API は REST で動作します。リクエストは JSON を返します。

6 つのデータ クラス (ユーザー、タスク、プロジェクトなど) があり、それぞれに REST 要求から返されたデータを保持する一連の文字列が含まれます。これらのクラスに関する私の最初のアイデアは、各ファクトリ Parse() コンストラクターを提供して、json を簡単に渡してデータ オブジェクトを取得できるようにすることです。静的ファクトリ メソッドをインターフェイスに抽出できないことに気付きました。

REST サーバーからのデータの送受信を管理する REST 要求クラスがあります。常に JSON 文字列を返します。

最後に、REST サーバーで公開されているメソッドをラップするメソッドを含む AsanaAPI クラス (つまり、GetUser、GetAllUsers、GetTask) が必要です。すべてのメソッドは、特定のデータ クラスまたはデータ クラスの配列のいずれかを返します。以下に 2 つのケースを示します。

    public User GetSingleUser(string userID = "me")
    {
        if(userID == "") throw new ArgumentException("UserID cannot be blank");

        string url = string.Format("{0}/{1}{2}", userUrl, userID, "?opt_fields=id,name,email,workspaces,workspaces.id,workspaces.name");
        JSONNode root = JSON.Parse(GetResponse(url))["data"];
        return User.Parse(root);
    }

    public List<User> GetAllUsers()
    {
        List<User> users = new List<User>();

        string url = string.Format("{0}{1}", userUrl, "?opt_fields=id,name,email,workspaces,workspaces.id,workspaces.name");
        JSONArray root = JSON.Parse(GetResponse(url))["data"].AsArray;
        foreach(JSONNode userRoot in root)
        {
            users.Add(User.Parse(userRoot));
        }

        return users;
    }

各メソッドの形式は同じですが、User タイプは Project、Task などに置き換えられます。ほぼ同じ形式のメソッドがさらに多くあるため、これら 2 つのメソッドのロジックを抽出したいと思います。

要約すると、私が遭遇した障害は、

  1. データ クラスからファクトリ コンストラクター メソッドを抽出できません。
  2. リクエスト メソッドから解析ロジックを抽出できません

ジェネリックでできることはありますか、またはこのプロジェクトを設計するためのより良い方法はありますか?

4

1 に答える 1

0

そこで、Parse メソッドのみを含む Parsable インターフェイスを作成しました。各データ型は Parsable を実装しています。ジェネリック型を使用して解析ロジックを抽出できました。それは最も美しい解決策ではありませんが、うまくいきます。

    public User GetSingleUser(string userID = "me")
    {
        if(userID == "") throw new ArgumentException("UserID cannot be blank");

        string url = "{baseUrl}/users/{userID}?{opt_fields}".FormatWith(
            new { baseUrl = BASE_URL, userID = userID, opt_fields = "opt_fields=id,name,email,workspaces,workspaces.id,workspaces.name" });

        return (User)ParseJson<User>(AsanaRequest.GetResponse(url));
    }

    public User[] GetAllUsers()
    {
        string url = "{baseUrl}/users?{opt_fields}".FormatWith(
            new { baseUrl = BASE_URL, opt_fields = "opt_fields=id,name,email,workspaces,workspaces.id,workspaces.name" });

        return (User[])ParseJsonArray<User>(AsanaRequest.GetResponse(url));
    }

    public T ParseJson<T>(string json) where T : Parsable, new()
    {
        JSONNode root = JSON.Parse(json)["data"];
        T ret = new T();
        ret.Parse(root);
        return ret;
    }

    public T[] ParseJsonArray<T>(string json) where T : Parsable, new()
    {
        JSONArray root = JSON.Parse(json)["data"].AsArray;
        T[] nodes = new T[root.Count];
        for(int i = 0; i < root.Count; i++)
        {
            T newParsable = new T();
            newParsable.Parse(root[i]);
            nodes[i] = newParsable;
        }

        return nodes;
    }
于 2013-03-03T01:20:13.460 に答える