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の答えは、これを完了するための答えを私に与えました-実行時までわからない、複数のソート基準を処理できるソーターを実装する必要がありました。私はマークの答えを受け入れていますが、誰かがそれを役立つかもしれないのでこれを投稿してください。

これを達成するためのよりエレガントな方法があるかもしれません。もしそうなら、私に知らせてください、そして私は答えを更新します。

 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 に答える