2013-03-02 3 views
0

Я разрабатываю API-оболочку в C# для Asana, решение для управления проектами. Во время процесса проектирования я столкнулся с несколькими блокпостами. Мне интересно, какой хороший способ создать API-оболочку.Asana API C# Project Design

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

Каждый метод будет иметь тот же формат, но тип пользователя будет заменен проектом, задача и т.д. Я хочу, чтобы извлечь логику в этих двух методах, потому что там будет много больше методов с почти одинаковым форматом.

В заключение, блокпосты я столкнулся, были в том, что

  1. Я не могу извлечь Фабричный метод конструктора из класса данных.
  2. Я не могу извлечь разбор логики из методов запроса

Есть ли что-то я могу сделать с обобщениями или там просто лучшим способом разработки этого проекта?

ответ

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