यहाँ कुछ नए गुर उपयोग कर एक नया implmentation है।
IList<T>
के अंतर्निहित प्रकार void Sort(Comparison<T>)
को लागू करना चाहिए या आप एक प्रतिनिधि में पारित करना होगा आप के लिए तरह समारोह कॉल करने के लिए।
(IList<T>
एक void Sort(Comparison<T>)
समारोह नहीं है) स्थिर निर्माता वर्ग प्रकार T
के माध्यम से जाना होगा सभी सार्वजनिक instanced गुण है कि ICompareable
या ICompareable<T>
लागू करता है और प्रतिनिधियों इसे बाद में उपयोग के लिए बनाता है कैश की खोज के दौरान। यह एक स्थिर कन्स्ट्रक्टर में किया जाता है क्योंकि हमें प्रति दिन T
और Dictionary<TKey,TValue>
पढ़ने पर थ्रेड सुरक्षित होने पर केवल इसे करने की आवश्यकता होती है।
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
namespace ExampleCode
{
public class SortableBindingList<T> : BindingList<T>
{
private static readonly Dictionary<string, Comparison<T>> PropertyLookup;
private readonly Action<IList<T>, Comparison<T>> _sortDelegate;
private bool _isSorted;
private ListSortDirection _sortDirection;
private PropertyDescriptor _sortProperty;
//A Dictionary<TKey, TValue> is thread safe on reads so we only need to make the dictionary once per type.
static SortableBindingList()
{
PropertyLookup = new Dictionary<string, Comparison<T>>();
foreach (PropertyInfo property in typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance))
{
Type propertyType = property.PropertyType;
bool usingNonGenericInterface = false;
//First check to see if it implments the generic interface.
Type compareableInterface = propertyType.GetInterfaces()
.FirstOrDefault(a => a.Name == "IComparable`1" &&
a.GenericTypeArguments[0] == propertyType);
//If we did not find a generic interface then use the non-generic interface.
if (compareableInterface == null)
{
compareableInterface = propertyType.GetInterface("IComparable");
usingNonGenericInterface = true;
}
if (compareableInterface != null)
{
ParameterExpression x = Expression.Parameter(typeof(T), "x");
ParameterExpression y = Expression.Parameter(typeof(T), "y");
MemberExpression xProp = Expression.Property(x, property.Name);
Expression yProp = Expression.Property(y, property.Name);
MethodInfo compareToMethodInfo = compareableInterface.GetMethod("CompareTo");
//If we are not using the generic version of the interface we need to
// cast to object or we will fail when using structs.
if (usingNonGenericInterface)
{
yProp = Expression.TypeAs(yProp, typeof(object));
}
MethodCallExpression call = Expression.Call(xProp, compareToMethodInfo, yProp);
Expression<Comparison<T>> lambada = Expression.Lambda<Comparison<T>>(call, x, y);
PropertyLookup.Add(property.Name, lambada.Compile());
}
}
}
public SortableBindingList() : base(new List<T>())
{
_sortDelegate = (list, comparison) => ((List<T>)list).Sort(comparison);
}
public SortableBindingList(IList<T> list) : base(list)
{
MethodInfo sortMethod = list.GetType().GetMethod("Sort", new[] {typeof(Comparison<T>)});
if (sortMethod == null || sortMethod.ReturnType != typeof(void))
{
throw new ArgumentException(
"The passed in IList<T> must support a \"void Sort(Comparision<T>)\" call or you must provide one using the other constructor.",
"list");
}
_sortDelegate = CreateSortDelegate(list, sortMethod);
}
public SortableBindingList(IList<T> list, Action<IList<T>, Comparison<T>> sortDelegate)
: base(list)
{
_sortDelegate = sortDelegate;
}
protected override bool IsSortedCore
{
get { return _isSorted; }
}
protected override ListSortDirection SortDirectionCore
{
get { return _sortDirection; }
}
protected override PropertyDescriptor SortPropertyCore
{
get { return _sortProperty; }
}
protected override bool SupportsSortingCore
{
get { return true; }
}
private static Action<IList<T>, Comparison<T>> CreateSortDelegate(IList<T> list, MethodInfo sortMethod)
{
ParameterExpression sourceList = Expression.Parameter(typeof(IList<T>));
ParameterExpression comparer = Expression.Parameter(typeof(Comparison<T>));
UnaryExpression castList = Expression.TypeAs(sourceList, list.GetType());
MethodCallExpression call = Expression.Call(castList, sortMethod, comparer);
Expression<Action<IList<T>, Comparison<T>>> lambada =
Expression.Lambda<Action<IList<T>, Comparison<T>>>(call,
sourceList, comparer);
Action<IList<T>, Comparison<T>> sortDelegate = lambada.Compile();
return sortDelegate;
}
protected override void ApplySortCore(PropertyDescriptor property, ListSortDirection direction)
{
Comparison<T> comparison;
if (PropertyLookup.TryGetValue(property.Name, out comparison))
{
if (direction == ListSortDirection.Descending)
{
_sortDelegate(Items, (x, y) => comparison(y, x));
}
else
{
_sortDelegate(Items, comparison);
}
_isSorted = true;
_sortProperty = property;
_sortDirection = direction;
OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, property));
}
}
protected override void RemoveSortCore()
{
_isSorted = false;
}
}
}
के लिए SupportsSortingCore, IsSortedCord, SortDirectionCore, SortPropertyCore और RemoveSortCore को ओवरराइड करना चाहिए, कुछ पिछले डेवलपर ने इसे विन फॉर्म प्रोजेक्ट में उसी तरह कार्यान्वित किया है, जिस पर मैं काम कर रहा हूं, और मैं समझना चाहता हूं कि क्यों। अब मुझे पता है; यह बेहतर प्रदर्शन है। यह एक अविश्वसनीय रूप से सहायक पोस्ट था, क्योंकि यह न केवल आपको समाधान को कार्यान्वित करने का तरीका दिखाता है, बल्कि यह बताता है कि इस समाधान में कौन से परिदृश्य बेहतर हैं। +1 – Jim
सुझाव: उपरोक्त कोड संशोधित करने वाली फ़ाइल में एक लिंक जोड़ें। –
मैं सूची में उलटा होने पर दो बार सॉर्ट करने की बजाए एक छोटा बदलाव सुझाता हूं, तुलनात्मक रूप से तुलना करें 'तुलना तुलनाकर्ता = GetComparer (prop); अगर (दिशा == ListSortDirection.Descending) {var original = comparr; तुलनाकर्ता = (एक्स, वाई) => मूल (वाई, एक्स); } itemsList.Sort (तुलनात्मक); ' –