2012-02-11 5 views
3

фон

Я работаю над приложением, которое требует потребления JSON услуг на сервере, а затем переупаковка этого JSON в модели представления, которые можно ссылаться с использованием синтаксиса Razor в представлении. Обработка на стороне сервера этого кода является обязательной по различным причинам.Каков самый быстрый способ итерации динамического объекта в C#?

Мы используем C#, .NET 4, MVC3, Razor, JsonFx.

В настоящее время у нас есть код, который работает очень хорошо, но он занимает минуту, чтобы перебрать 250 предметов в полученном объекте JSON, и это неприемлемо (не говоря уже о недоумении). Я уже выделил проблему для следующего цикла; JSON приходит быстро, так что это не проблема. Вот работает, но очень медленно код:

 var reader = new JsonReader(); 
     var json = GetJson(SPListName); 

     var admItems = new List<IDictionary<String, object>>(); 
     dynamic _items = reader.Read(json); //This part is REALLY fast. No problem here. 
     foreach (var itm in _items) 
     { 
      dynamic obj = new ExpandoObject(); 
      foreach (dynamic admObj in itm)//Here begins the slow part. 
      { 
       var item = obj as IDictionary<String, object>; 
       var encodedValue = ""; 
       try 
       { 
        if(admObj.Key == "Title") 
        { 
         encodedValue = admObj.Value.ToString(); 
        }else 
        { 
         encodedValue = admObj.Value[0].ToString(); 
        } 
       } 
       catch (Exception) 
       { 
        encodedValue = admObj.Value.ToString();     
       } 

       item[admObj.Key] = encodedValue.EncodeNonAscii().FixHtmlEntities(); 
      } 
      admItems.Add(obj); 
     } 
     return admItems; 

Вы также можете заметить несколько методов пользовательских расширений. Вот они (в случае, если имеет значение):

public static string EncodeNonAscii(this Object str) 
      { 
       StringBuilder sb = new StringBuilder(); 
       foreach (char c in str.ToString()) 
       { 
        if (c > 127) 
        { 
         // This character is too big for ASCII 
         string encodedValue = "\\u" + ((int) c).ToString("x4"); 
         sb.Append(encodedValue); 
        } 
        else 
        { 
         sb.Append(c); 
        } 
       } 
       return sb.ToString(); 
      } 

      public static string FixHtmlEntities(this Object str) 
      { 
       var fixedString = str.ToString().Replace("\\u00c2\\u00ae", "&reg;"); 
       return fixedString; 
      } 

Вопрос

Какого черта я делаю неправильно/как я ускорить это. Мой мозг - гамбургер прямо сейчас, поэтому я надеюсь, что кто-то указывает на простой надзор.

Update Разрешение/

Rophuine и Джошуа Enfield и указал на корень вопроса скорости: на отлов исключений было замедляя все вниз.

Многие люди предлагали использовать Json.Net или что-то подобное. Хотя я ценю этот совет, это действительно не лежало в основе моей проблемы (хотя, возможно, это и было так); Я использовал Json.Net в прошлом в прошлом и предпочел JsonFx над ним несколько месяцев назад. В этом конкретном случае я больше интересуюсь конструкцией объекта модели представления, поскольку я уже десериализую JSON с использованием JsonFx. Пожалуйста, дайте мне знать, если вы все еще думаете, что мне не хватает вашей точки;).

Причина, по которой моя мозговая схема try/catch была в том, что мне нужно было делать разные вещи с каждым свойством строки JSON в зависимости от ее типа (строка, строка [], объект [] и т. Д.). Я забыл, что System.Type может справиться с этим для меня. Итак, вот окончательный код:

var reader = new JsonReader(); 
       var json = GetJson(SPListName); 

       var admItems = new List<IDictionary<String, object>>(); 
       dynamic _items = reader.Read(json); 
       foreach (var itm in _items) 
       { 
        dynamic obj = new ExpandoObject(); 
        foreach (dynamic admObj in itm) 
        { 
         var item = obj as IDictionary<String, object>; 
         var encodedValue = ""; 

         Type typeName = admObj.Value.GetType(); 

         switch (typeName.ToString()) 
         { 
          case("System.String[]"): 
           encodedValue = admObj.Value[0].ToString(); 
           break; 
          default: 
           encodedValue = admObj.Value.ToString(); 
           break; 
         } 

         item[admObj.Key] = encodedValue.EncodeNonAscii().FixHtmlEntities(); 
        } 
        admItems.Add(obj); 
       } 
       return admItems; 

Надеюсь, это поможет кому-то!

+0

Сколько исключений происходит?Если обработка обработки исключений в пограничных потоках может замедлить некоторые из них, но минута звучит ужасно долго для 250 предметов. Вам действительно нужно использовать динамику здесь? –

+2

Есть ли причина, по которой вы не используете json-библиотеку, такую ​​как JSON.NET или ServiceStack.NET? Легче (а также быстро) разбирать строку json. –

+0

В дополнение к @ Ni'am, вы можете иметь словарь объектов с одной строкой кода 'JsonConvert.DeserializeObject'. Примеры: http://stackoverflow.com/questions/8662233/parsing-non-standard-json/8662323#8662323 http://stackoverflow.com/questions/8887029/parsing-json-file-c-sharp/8887177#8887177 –

ответ

6
  try 
      { 
       if(admObj.Key == "Title") 
       { 
        encodedValue = admObj.Value.ToString(); 
       }else 
       { 
        encodedValue = admObj.Value[0].ToString(); 
       } 
      } 
      catch (Exception) 
      { 
       encodedValue = admObj.Value.ToString();     
      } 

Я не имею C# компилятор передо мной, или получить доступ к данным, но это выглядит подозреваемого мне. Исключения составляют extreme slow - вы часто нажимаете на блок catch? Если да, попробуйте выяснить, что вызывает исключения, и обрабатывать их, не вызывая исключения, - оставляйте исключения для обработки редких ситуаций, о которых вы не думали.

Редактировать: Окончательное решение находится в вопросе редактирования - я не буду повторять его здесь. Если у вас проблема с производительностью, и у вас есть обработка исключений где-то в вашем цикле, это часто самое первое, что можно попытаться устранить. Исключения ужасно медленны - гораздо больше, чем вы могли бы подумать. Их лучше всего хранить в необычных обстоятельствах.

+0

Cheers Rophuine! Спасибо за помощь. Пожалуйста, см. Мое последнее обновление выше и не стесняйтесь включать любой из них в свой ответ по своему усмотрению. –

+0

По-видимому, исключения выполняются только в режиме отладки, однако, как видно из названия, исключения должны быть исключением, а не правилом. http://yoda.arachsys.com/csharp/exceptions.html –

Смежные вопросы