【问题标题】:Dynamic Sorting with a SerializableDynamicObject使用 SerializableDynamicObject 进行动态排序
【发布时间】:2012-06-27 17:30:26
【问题描述】:

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

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

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

  PropertyInfo pi = type.GetProperty(prop);

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

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

我查看了this 示例,但收到错误消息:

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

【问题讨论】:

    标签: c# xml wcf serialization dynamic


    【解决方案1】:

    这里有一些使用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);
                }
            }
        }
    }
    

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

    【讨论】:

    • 太棒了 - 感谢 Marc 以及对您其他帖子的有用评论 - 否则我会花费很长时间试图朝着错误的方向前进。
    【解决方案2】:

    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"}
    

    【讨论】:

    • 我主要关心的是你拨打ToUpper的次数。小心那个!我将首先将其测试为bool。事实上,您希望在Compare(x,y)几乎什么都不做 - 这将被调用lots。而是在构造函数中执行。
    • 是的 - 非常好! - 将更正和更新 - 再次感谢!
    猜你喜欢
    • 2016-01-29
    • 1970-01-01
    • 2016-09-13
    • 2018-01-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-06
    • 1970-01-01
    相关资源
    最近更新 更多