使用SerializableDynamicObject进行动态排序

我需要根据运行时确定的标准对这些集合进行排序。

我使用本文中的代码来执行排序 – 最初我的代码使用了动态类。

然后我遇到了通过WCF进行序列化的问题,所以我切换到使用SerializableDynamicObject ,现在排序代码中断了:

PropertyInfo pi = type.GetProperty(prop); 

具有Seri​​alizableDynamicObject没有名为“Name”的属性的错误 – 其中“Name”是prop的值。

我想最简单的方法是找到一种序列化排序算法的动态类型的替代方法。 任何指向这个方向将不胜感激!

我看过这个例子,但是收到错误信息:

 The constructor with parameters (SerializationInfo, StreamingContext) is not found in ISerializable type 

下面是使用FastMember的一些代码,它适用于基于reflection和基于dynamic的对象(取决于您传递给TypeAccessor.Create

 using System; using System.Collections; using System.Collections.Generic; using System.Dynamic; using FastMember; namespace ConsoleApplication6 { class Program { static void Main() { var list = new List(); dynamic obj = new ExpandoObject(); obj.Foo = 123; obj.Bar = "xyz"; list.Add(obj); obj = new ExpandoObject(); obj.Foo = 456; obj.Bar = "def"; list.Add(obj); obj = new ExpandoObject(); obj.Foo = 789; obj.Bar = "abc"; list.Add(obj); var accessor = TypeAccessor.Create( typeof(IDynamicMetaObjectProvider)); string propName = "Bar"; list.Sort((x,y) => Comparer.Default.Compare( accessor[x, propName], accessor[y,propName])); foreach(var item in list) { Console.WriteLine(item.Bar); } } } } 

值得注意的是,对于基于reflection的类型,这不会在每个项目的基础上使用reflection; 所有这些都是通过元编程优化的。

Marc Gravell的回答给了我完成这个的答案 – 我需要实现一个可以处理多个排序标准的分类器,直到运行时才知道。 我接受了Marc的回答,但发布这个有人可能会发现它也很有用。

可能有更优雅的方式来实现这一点,如果是这样,请告诉我,我会更新答案。

  public class SerializableDynamicObjectComparer: IComparer { private readonly List> sortCriteria = new List>(); private readonly TypeAccessor accessor; public SerializableDynamicObjectComparer(IEnumerable criteria) { foreach (var criterium in criteria) { string[] sortCriterium = criterium.Split('.'); this.sortCriteria.Add(new KeyValuePair(sortCriterium[0], sortCriterium.Length == 0 ? sortCriterium[1].ToUpper() == "ASC" : false)); } this.accessor = TypeAccessor.Create(typeof (IDynamicMetaObjectProvider)); } public int Compare(object x, object y) { for(int i=0; i< this.sortCriteria.Count; i++) { string fieldName = this.sortCriteria[i].Key; bool isAscending = this.sortCriteria[i].Value; int result = Comparer.Default.Compare(this.accessor[x, fieldName], this.accessor[y, fieldName]); if(result != 0) { //If we are sorting DESC, then return the -ve of the default Compare result return isAscending ? result : -result; } } //if we get here, then objects are equal on all sort criteria. return 0; } } 

用法:

 var sorter = new SerializableDynamicObjectComparer(sortCriteria); var sortableData = reportData.ToList(); sortableData.Sort(sorter.Compare); 

其中sortCriteria是一个字符串数组,例如

  new {"Name.DESC", "Age.ASC", "Count"}