如何在不使用反射的情况下按名称动态访问属性?

时间:2011-02-18 17:06:34

标签: c# performance reflection dynamic properties

起初我正在使用:

sortedList = unsorted.AsParallel().OrderBy(myItem => TypeDescriptor.GetProperties(myItem)[firstSort.Item2].GetValue(myItem));

其中firstSort.Item2是属性的字符串名称。但是,随着未排序列表中的项目数量的增加,性能显着下降。 (正如我所料)

有没有办法在不使用反射的情况下执行此操作?

蛮力方法是做类似的事情:

if(firstSort.Item2 == "Size")
   sortedList = unsorted.AsParallel().OrderBy(myItem => myItem.Size);
else if(firstSort.Item2 == "Price")
   sortedList = unsorted.AsParallel().OrderBy(myItem => myItem.Price);
...

我正在寻找能够完成上述行为的东西,但无需在界面中的所有不同属性中进行硬编码。

7 个答案:

答案 0 :(得分:3)

您可以use Expression<T> to pre-compile传递给OrderBy的表达式。然后你可以在运行时查找它们。

答案 1 :(得分:2)

您使用的所有内容都不涉及硬编码的实际属性列表,将使用“幕后”反射。

答案 2 :(得分:1)

您可以创建一次PropertyInfo并使用它在多个目标对象上调用GetValue。这比为列表中的每个项调用TypeDescriptor.GetProperties要便宜得多。

另外,尝试删除AsParallel - 开销实际上可能会降低性能,而不是在这种情况下帮助它。

试试这个:

var prop = unsorted.GetType().GetGenericArguments()[0].GetProperty(firstSort.Item2);
sortedList = unsorted.OrderBy(myItem => prop.GetValue(myItem, null));

答案 3 :(得分:0)

如果您在班级中实施ICustomTypeDescriptor,那么在使用TypeDescriptor时可以避免反射。

当然,我假设您拥有myItem的类型。

答案 4 :(得分:0)

最好的办法是使用Microsoft提供的Dynamic LINQ库。

这是一个链接:http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx

答案 5 :(得分:0)

我喜欢Roger的答案最适合真正的解决方案,但是如果你想要一些简单的东西,你可以构建一个小代码生成器来获取类并将其属性分解为字符串到lambda的字典,代表每个属性。在运行时,您可以从此字典中调用以检索适当的lambda。

答案 6 :(得分:0)

您可以使用DLR。开源框架Impromptu-Interface在幕后完成所有dlr管道,并获取属性2.5x faster than reflection的值。

sortedList = unsorted.AsParallel().OrderBy(myItem => Impromptu.InvokeGet(myItem,firstSort.Item2));