От объекта к надлежащему типу: это / "правильный" способ работы с этим не генерируемым, возвращающим объект API? - PullRequest
0 голосов
/ 25 июня 2010

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

Я использую не обобщенный, object возвращаемый JSON-анализатор, который заставляет меня идтичерез различные заклинания в моем обобщенном коде.

Подпись метода разбора public static object JsonDecode(string json) Тип времени выполнения возвращаемого объекта может быть ArrayList, Hashtable, double или string.Я вызываю метод JsonDecode в ответе на поиск в Twitter, который возвращает полученные твиты в виде объекта верхнего уровня в форме:

{"results":[
 {"text":"@twitterapi  http:\/\/tinyurl.com\/ctrefg",
 "to_user_id":396524,
 "to_user":"TwitterAPI",
 "from_user":"jkoum",
 "metadata":
 {
  "result_type":"popular",
  "recent_retweets": 109

 }, ... MORE-DATA ...}

Контекст, в котором я использую JsonDecode(string json)метод

private IList<Tweet> searchResult = new List<Tweet>();
var jsonDecoded = JSON.JsonDecode(responseString);

IList rawTweets = 
    (IList)((Hashtable)jsonDecoded)["results"];

foreach (var rawTweet in rawTweets) 
{
    searchResult.Add(new Tweet((Hashtable) rawTweet));
}

Класс Tweet выполняет собственную проверку типов и приведение типов

 class Tweet : DynamicObject
{
    private IDictionary<string, string> stringValues = 
        new Dictionary<string, string>();
    private IDictionary<string, double> numberValues =
        new Dictionary<string, double>();

    public Tweet(Hashtable rawTweet) 
    {
        FlattenJSON(rawTweet);
    }

    //flatten input and assign to correct map/dictionary based on JSON value type
    private void FlattenJSON(Hashtable table)
    {
        foreach (DictionaryEntry entry in table)
        {
            //this code is not handling the case, that the Tweet contains a JSON array
            //not necessary as of now: this code is intended for demo purposes in a talk
            //I'm giving on Friday 2010-06-25
            if (entry.Value is String)
                stringValues.Add((string)entry.Key, (string)entry.Value);
            else if (entry.Value is Double)
                numberValues.Add((string)entry.Key, (double)entry.Value);
            else if (entry.Value is Hashtable)
                FlattenJSON((Hashtable)entry.Value);
        }
    }
    ...
}

Правильно ли я обрабатываю проверки типов в методе FlattenJSON?А как насчет приведений во фрагменте кода для построения IList и построения searchResult IList<code><Tweet> ?Вы бы написали код по-другому?

В качестве примечания, полный код доступен через http://github.com/codesurgeon/pop-tweets Код предназначен для демонстрации в лекции, которую я буду даватьна выбранные функции .NET.Класс Tweet - это DynamicObject и он переопределяет TryGetMember, см. Полный список на github.

Спасибо;)

PS: [FYI] Это более конкретная версиямоего предыдущего поста с просьбой пересмотреть общий код https://stackoverflow.com/questions/3113293/how-to-be-a-good-c-citizen-review-requested-for-c-4-0-dynamic-sample-code

Ответы [ 2 ]

2 голосов
/ 25 июня 2010

Несколько вещей выделяются для меня:

Во-первых, вам следует проверить аргумент.Проверьте, является ли «таблица» пустым, прежде чем начать ее использовать.В противном случае вы получите необработанное исключение NullReferenceException, которое запутает вашего потребителя.

Далее, это на самом деле работает?Ключевое слово «is» (я думал) работает только со ссылочными типами, а double является типом значения.Я бы предположил, что это не сработает, и вам вместо этого нужно было бы выполнить double.TryParse ().

Наконец, существует много кастингов на лету.Когда вы взаимодействуете со сторонним API, я бы сказал, что у вас должен быть интерфейс, в котором вы конвертируете «их странные вещи» в «ваши чистые вещи».Так что, даже если API неопрятный и сложный, приведите его в порядок и представьте его потребителю надлежащим образом.Не пропагандируйте плохой дизайн.Другими словами, будучи разработчиком-потребителем, я хотел бы работать с некоторыми очевидными и чистыми структурами данных.Например: foreach (твит в Твиттере. GetTweets ()) или что-то в этом роде.Мне все равно, что вы используете JSON прямо сейчас.Эта реализация должна быть невидима для меня.

Надеюсь, это поможет ...

0 голосов
/ 25 июня 2010

Я бы так не поступил.

Прежде всего, ваш класс твитов - это не реальный объект, это контейнер данных.Вы можете просто продолжать работать с переменной jsonDecoded , поскольку ваш класс твитов не добавляет никакой функциональности или абстракции (кроме абстрагирования от JSON-декодера).

Как бы я это сделал:

  1. Создать POCO s, который содержит информацию: Tweet и класс метаданных.
  2. Создать сериализатор, который принимает строку JSON и возвращает класс Tweet

Разделив его на два этапа, а также создавая реальные классы, вам будет намного легче в будущем.Пожалуйста, прочитайте о Одиночная ответственность .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...