1

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

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

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

  PropertyInfo pi = type.GetProperty(prop);

错误是 SerializableDynamicObject 没有名为“Name”的属性 - 其中“Name”是 prop 的值。

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

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

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

2 回答 2

2

这是一些使用FastMember的代码,它适用于基于反射和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>();
            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);
            }
        }
    }
}

值得一提的是,对于基于反射的类型,这不会每个项目的基础上使用反射;所有这些都通过元编程进行了优化。

于 2012-06-26T12:10:25.560 回答
0

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

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

 public class SerializableDynamicObjectComparer: IComparer
{
    private readonly List<KeyValuePair<string, bool>> sortCriteria = new List<KeyValuePair<string, bool>>();

    private readonly TypeAccessor accessor;

    public SerializableDynamicObjectComparer(IEnumerable<string> criteria)
    {
        foreach (var criterium in criteria)
        {
            string[]  sortCriterium = criterium.Split('.');

            this.sortCriteria.Add(new KeyValuePair<string, bool>(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"}
于 2012-06-26T14:05:45.330 回答