C# 如何在不使用反射的情况下按名称动态访问属性?
起初我使用的是:C# 如何在不使用反射的情况下按名称动态访问属性?,c#,performance,reflection,dynamic,properties,C#,Performance,Reflection,Dynamic,Properties,起初我使用的是: sortedList = unsorted.AsParallel().OrderBy(myItem => TypeDescriptor.GetProperties(myItem)[firstSort.Item2].GetValue(myItem)); 其中firstSort.Item2是属性的字符串名称。但是,随着未排序列表中项目数量的增加,性能显著降低。(如我所料) 有没有一种不使用反射的方法可以做到这一点 蛮力方法将采取如下措施: if(firstSort.Item
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);
...
我正在寻找能够实现上述行为的东西,但不必硬编码接口中的所有不同属性。您使用的所有不涉及实际属性硬编码列表的东西都将在“幕后”使用反射。如果您在类中实现,然后在使用TypeDescriptor时可以避免反射
当然,我假设您拥有
myItem
的类型,您可以使用传递给OrderBy
的表达式。然后您可以在运行时查找它们。您最好使用Microsoft提供的动态LINQ库
这里有一个链接:您可以创建一次PropertyInfo,并使用它在多个目标对象上调用GetValue。这比为列表中的每个项目调用TypeDescriptor.GetProperties要便宜得多 另外,尝试删除AsParallel-在这种情况下,开销实际上可能会降低性能,而不是帮助性能 试试这个:
var prop = unsorted.GetType().GetGenericArguments()[0].GetProperty(firstSort.Item2);
sortedList = unsorted.OrderBy(myItem => prop.GetValue(myItem, null));
对于真正的解决方案,我喜欢Roger的答案,但是如果您想要一些简单的东西,您可以构建一个小型代码生成器来获取类,并将其属性分解到一个字符串到lambda的字典中,表示每个属性。在运行时,您可以从此字典中调用以检索相应的lambda。您可以使用DLR。开源框架在幕后执行所有dlr管道,并获取属性的值
您是否尝试过在OrderBy之外以及在OrderBy中使用TypeDescriptor.GetProperties(myItem)[firstSort.Item2].GetValue(myItem)后使用它?第二种解决方案的速度要快多少?是的,但我不想每次访问该属性时都进行反思。有没有一种方法可以让我决定使用反射访问哪个属性,然后让它排序,而不必每次都获取值?@Chris:GetValue是获取属性值的方式。因为每个对象都不同,所以必须为每个对象调用它。好的,我想我应该澄清一下……如何才能最大限度地减少使用反射对性能的影响。性能是一个实际问题吗?或者这是一个可感知的问题?你分析过了吗?当然!列表中最多有1000万个项目…反射访问是这种类型的热门途径。我尝试了这种方法…性能有了一点改进,但仍然非常缓慢。尽管如此,阿斯帕莱尔绝对值得。当列表中的项目超过100万个时,我会得到2-5倍的加速。我想这可能会给我的场景带来最好的结果。现在调查一下。
sortedList = unsorted.AsParallel().OrderBy(myItem => Impromptu.InvokeGet(myItem,firstSort.Item2));