0

我正在用 C# 为Asana设计一个 API 包装器,这是一个项目管理解决方案。在设计过程中,我遇到了一些障碍。我想知道设计 API 包装器的好方法是什么。

我正在集成的 Asana API 与 REST 配合使用。请求返回 JSON。

将有 6 个数据类(用户、任务、项目等),每个类都包含一堆字符串来保存从 REST 请求返回的数据。我对这些类的第一个想法是给它们每个工厂 Parse() 构造函数,这样我就可以轻松地传入 json 并获得一个数据对象作为回报。我意识到我无法将静态工厂方法提取到接口中。

我将有一个 REST 请求类来管理从 REST 服务器发送和接收数据。它总是会返回一个 JSON 字符串。

最后,我想要一个 AsanaAPI 类,它包含包装那些暴露在 REST 服务器上的方法(即 GetUser、GetAllUsers、GetTask)。每个方法要么返回一个特定的数据类,要么返回一个数据类数组。以下是两种情况:

    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 等。我想提取这两个方法中的逻辑,因为会有更多具有几乎完全相同格式的方法。

总之,我遇到的障碍是

  1. 我无法从数据类中提取工厂构造方法。
  2. 我无法从请求方法中提取解析逻辑

有什么我可以用泛型做的,还是有更好的方法来设计这个项目?

4

1 回答 1

0

所以我创建了一个 Parsable 接口,它只包含一个 Parse 方法。每种数据类型都实现 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 回答