[英]What is the fastest way to iterate a dynamic object in C#?
I am working on an application that requires the consumption of JSON services on the server , and then repackaging of that JSON into a view model that can be referenced using Razor syntax in the view. 我正在开发一个需要在服务器上使用JSON服务的应用程序,然后将该JSON重新打包到可以在视图中使用Razor语法引用的视图模型中。 Server-side manipulation of this code is a must for various reasons.
出于各种原因,必须对此代码进行服务器端操作。
We are using C#, .NET 4, MVC3, Razor, JsonFx. 我们使用的是C#,.NET 4,MVC3,Razor,JsonFx。
We currently have code that works just fine, but it is taking up to a minute to iterate 250 items in the received JSON object and this is unacceptable (not to mention baffling). 我们目前的代码工作得很好,但是在接收到的JSON对象中迭代250个项目需要花费一分钟时间,这是不可接受的(更不用说令人费解了)。 I have already isolated the problem to the following loop;
我已经将问题隔离到以下循环中; the JSON comes in lightening-fast so that is not the problem.
JSON快速闪电,这不是问题所在。 Here is the working but extremely slow code:
这是工作但速度极慢的代码:
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;
You may also notice a few custom extension methods. 您可能还会注意到一些自定义扩展方法。 Here they are (in case that matters):
他们在这里(如果重要的话):
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", "®");
return fixedString;
}
What the heck am I doing wrong/how do I speed this up. 我到底做错了什么/如何加快速度呢? My brain is hamburger right now so I hope someone points out a simple oversight.
我的大脑现在是汉堡包,所以我希望有人指出一个简单的疏忽。
Rophuine and Joshua Enfield both pointed to the root of the speed issue: the catching of exceptions was slowing everything down. Rophuine和Joshua Enfield都指出了速度问题的根源:捕获异常会减慢一切。
Many folks suggested that I use Json.Net or something similar. 很多人建议我使用Json.Net或类似的东西。 While I appreciate that advice, it really wasn't at the root of my problem (even though it may have appeared that way);
虽然我很欣赏这个建议,但它确实不是我问题的根源(即使它可能是这样出现的); I have used Json.Net extensively in the past and came to prefer JsonFx over it a few months ago.
我过去曾经广泛使用过Json.Net,几个月前更喜欢JsonFx 。 In this particular case, I am more concerned with the construction of a view model object as I have already deserialized the JSON using JsonFx.
在这种特殊情况下,我更关心构建视图模型对象,因为我已经使用JsonFx对JSON进行了反序列化。 Please let me know if you still think I am missing your point ;).
如果你仍然认为我错过了你的观点,请告诉我;)。
The reason for my brain-dead try/catch scheme was that I needed to do different things with each property of the JSON string depending on it's type (string, string[], object[], etc). 我的脑死亡尝试/捕获方案的原因是我需要对JSON字符串的每个属性做不同的事情,具体取决于它的类型(字符串,字符串[],对象[]等)。 I forgot that System.Type can handle that for me.
我忘了System.Type可以为我处理。 So here is the final code:
所以这是最终的代码:
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;
Hope this helps someone! 希望这有助于某人!
try
{
if(admObj.Key == "Title")
{
encodedValue = admObj.Value.ToString();
}else
{
encodedValue = admObj.Value[0].ToString();
}
}
catch (Exception)
{
encodedValue = admObj.Value.ToString();
}
I don't have a C# compiler in front of me, or access to your data, but this looks suspect to me. 我面前没有C#编译器,也无法访问您的数据,但这对我来说很可疑。 Exceptions are extremely slow - are you hitting the catch block often?
例外情况非常缓慢 - 你经常遇到陷阱吗? If you are, try to work out what's causing the exceptions and handle them without causing an exception - leave exceptions to handle rare situations you haven't thought of.
如果是的话,尝试找出造成异常的原因并处理它们而不会导致异常 - 请保留异常以处理您未曾想到的罕见情况。
Edit: Final solution is in the question edit - I won't repeat it here. 编辑:最终解决方案在问题编辑中 - 我不会在这里重复。 If you have a performance problem and you have exception-handling somewhere in your loop, that's often the very first thing to try and eliminate.
如果您遇到性能问题并且在循环中的某个地方进行了异常处理,那么这通常是首先尝试消除的问题。 Exceptions are awfully slow - much more so than you might think.
例外情况非常缓慢 - 远比你想象的要多得多。 They're best kept for very unusual circumstances.
他们最好保留在非常特殊的情况下。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.