【发布时间】:2012-07-27 16:13:41
【问题描述】:
我在使用 C# 中的 System.Reflection 时遇到了一些问题。我正在从数据库中提取数据并在 JSON 字符串中检索该数据。我已经使用反射实现了将 JSON 中的数据处理到我自己声明的对象中的实现。但是,由于我通常会得到一个包含 50 到 100 个对象的数组的 JSON 字符串,因此我的程序运行速度非常慢,因为我使用了反射循环。
我听说反射很慢,但不应该这么慢。我觉得我的实现有些不对劲,因为我有一个不同的项目,我在其中使用 JSON.NET 序列化程序并用反射实例化我的对象有点不同,反射在相同的输出上运行得很好(不到一秒),而我的慢程序需要50 个对象大约需要 10 秒。
以下是我用来存储数据的类
class DC_Host
{
public string name;
public void printProperties()
{
//Prints all properties of a class usign reflection
//Doesn't really matter, since I'm not usign this for processing
}
}
class Host : DC_Host
{
public string asset_tag;
public string assigned;
public string assigned_to;
public string attributes;
public bool? can_print;
public string category;
public bool? cd_rom;
public int? cd_speed;
public string change_control;
public string chassis_type;
//And some more properties (around 70 - 80 fields in total)
您将在下面找到我将信息处理成存储在列表中的对象的方法。 JSON 数据存储在一个字典中,该字典包含另一个字典,用于在 JSON 输入中定义的每个数组对象。反序列化 JSON 会在几毫秒内完成,因此应该不会有问题。
public List<DC_Host> readJSONTtoHost(ref Dictionary<string, dynamic> json)
{
bool array = isContainer();
List<DC_Host> hosts = new List<DC_Host>();
//Do different processing on objects depending on table type (array/single)
if (array)
{
foreach (Dictionary<string, dynamic> obj in json[json.First().Key])
{
hosts.Add(reflectToObject(obj));
}
}
else
{
hosts.Add(reflectToObject(json[json.First().Key]));
}
return hosts;
}
private DC_Host reflectToObject(Dictionary<string,dynamic> obj)
{
Host h = new Host();
FieldInfo[] fields = h.GetType().GetFields();
foreach (FieldInfo f in fields)
{
Object value = null;
/* IF there are values that are not in the dictionairy or where wrong conversion is
* utilised the values will not be processed and therefore not inserted into the
* host object or just ignored. On a later stage I might post specific error messages
* in the Catch module. */
/* TODO : Optimize and find out why this is soo slow */
try
{
value = obj[convTable[f.Name]];
}
catch { }
if (value == null)
{
f.SetValue(h, null);
continue;
}
// Het systeem werkt met list containers, MAAAR dan mogen er geen losse values zijn dus dit hangt
// zeer sterk af van de implementatie van Service Now.
if (f.FieldType == typeof(List<int?>)) //Arrays voor strings,ints en bools dus nog definieren
{
int count = obj[convTable[f.Name]].Count;
List<int?> temp = new List<int?>();
for (int i = 0; i < count; i++)
{
temp.Add(obj[convTable[f.Name]][i]);
f.SetValue(h, temp);
}
}
else if (f.FieldType == typeof(int?))
f.SetValue(h, int.Parse((string)value));
else if (f.FieldType == typeof(bool?))
f.SetValue(h, bool.Parse((string)value));
else
f.SetValue(h, (string)value);
}
Console.WriteLine("Processed " + h.name);
return h;
}
我不确定 JSON.NET 在后台使用反射的实现是什么,但我假设他们使用我缺少的东西来优化他们的反射。
【问题讨论】:
-
为了获得最佳性能,需要生成新代码来填充数据。
-
但即使没有这个,充分利用字典和缓存应该可以大大加快您的代码速度。
-
然后摆脱那个空渔获物。
TryGetValueftw -
您可以在运行时发出新方法,将数据填充到对象中。所以你只需要反射来构建这些方法(
Reflection.Emit,Expression.Compile,...),而不是水合对象。 -
@JoeyDewd,尝试在不附加调试器的情况下运行慢速版本。你可能会对它的表现感到惊讶。杀死您的应用程序的是发生的许多异常。处理异常很昂贵,如果附加了调试器,则更是如此。经验教训:永远不要将异常用于常见的程序流控制。
标签: c# json optimization serialization reflection