/// <summary> /// 并行排序,并返回排序后的List列表 /// 自定义列与升倒序键值对 /// </summary> /// <param name="list"></param> /// <param name="sort">Key:名称,值:true:升序,false:倒序</param> public static void Sort <T>(this List <T> list, Dictionary <string, bool> sort) { if (sort == null || sort.Count == 0) { throw new ArgumentException("Sorting is not set."); } if (list.Count == 0) { return; } var item = sort.ElementAt(0); var type = list[0].GetType(); var builder = SortBuilder.CreateBuilder(type, item.Key, out bool iString); var property = type.Property(item.Key); OrderedParallelQuery <T> orderBy; if (iString) { orderBy = item.Value ? list.AsParallel().OrderBy(c => builder.Build(c) as string, new StringComparer()) : list.AsParallel().OrderByDescending(c => builder.Build(c) as string, new StringComparer()); } else { orderBy = item.Value ? list.AsParallel().OrderBy(c => builder.Build(c)) : list.AsParallel().OrderByDescending(c => builder.Build(c)); } for (int i = 1; i < sort.Count; i++) { item = sort.ElementAt(i); var builder2 = SortBuilder.CreateBuilder(type, item.Key, out iString); property = type.Property(item.Key); if (iString) { orderBy = item.Value ? orderBy.ThenBy(c => builder2.Build(c) as string, new StringComparer()) : orderBy.ThenByDescending(c => builder2.Build(c) as string, new StringComparer()); } else { orderBy = item.Value ? orderBy.ThenBy(c => builder2.Build(c)) : orderBy.ThenByDescending(c => builder2.Build(c)); } } var temp = orderBy.ToList(); list.Clear(); list.AddRange(temp); }
/// <summary> /// 生成动态代码,创建委托 /// </summary> public static SortBuilder CreateBuilder(Type type, string name, out bool iString) { iString = false; var property = type.Property(name); if (property == null) { throw new ArgumentException(name + " Argument can not be empty."); } if (!property.CanRead) { throw new ArgumentException("Cannot read value."); } var getTCompareInt = typeof(BuilderHelper).GetMethod(nameof(BuilderHelper.TCompareInt), TConfig.Flags, null, new Type[] { typeof(object) }, null); var getTCompareLong = typeof(BuilderHelper).GetMethod(nameof(BuilderHelper.TCompareLong), TConfig.Flags, null, new Type[] { typeof(object) }, null); var getTCompareDouble = typeof(BuilderHelper).GetMethod(nameof(BuilderHelper.TCompareDouble), TConfig.Flags, null, new Type[] { typeof(object) }, null); var dbType = property.PropertyType; if (dbType.IsGenericType && Nullable.GetUnderlyingType(dbType) != null) { dbType = Nullable.GetUnderlyingType(dbType); } if (dbType.IsEnum) { dbType = dbType.GetEnumUnderlyingType(); } var dymMethod = new DynamicMethod(type.Name + nameof(SortBuilder), typeof(string), new Type[] { typeof(object) }, true); switch (dbType.Name) { case nameof(Int32): case nameof(Int16): case nameof(Byte): case nameof(Boolean): case nameof(Image): case nameof(Bitmap): dymMethod = new DynamicMethod(type.Name + nameof(SortBuilder), typeof(int), new Type[] { typeof(object) }, true); break; case nameof(Int64): case nameof(DateTime): dymMethod = new DynamicMethod(type.Name + nameof(SortBuilder), typeof(long), new Type[] { typeof(object) }, true); break; case nameof(Double): case nameof(Single): case nameof(Decimal): dymMethod = new DynamicMethod(type.Name + nameof(SortBuilder), typeof(double), new Type[] { typeof(object) }, true); break; } var generator = dymMethod.GetILGenerator(); // Create ILGenerator generator.GetValue(property, type); //获取引用值 switch (dbType.Name) { case nameof(Int32): case nameof(Int16): case nameof(Byte): case nameof(Boolean): case nameof(Image): case nameof(Bitmap): generator.Emit(OpCodes.Call, getTCompareInt); //调用静态方法 break; case nameof(Int64): case nameof(DateTime): generator.Emit(OpCodes.Call, getTCompareLong); //调用静态方法 break; case nameof(Double): case nameof(Single): case nameof(Decimal): generator.Emit(OpCodes.Call, getTCompareDouble); //调用静态方法 break; default: //String不用再次转化 //generator.Emit(OpCodes.Call, getTCompareString);//调用静态方法 break; } generator.Emit(OpCodes.Ret); var builder = new SortBuilder(); switch (dbType.Name) { case nameof(Int32): case nameof(Int16): case nameof(Byte): case nameof(Boolean): case nameof(Image): case nameof(Bitmap): builder.handler = dymMethod.CreateDelegate(typeof(Func <object, int>)); break; case nameof(Int64): case nameof(DateTime): builder.handler = dymMethod.CreateDelegate(typeof(Func <object, long>)); break; case nameof(Double): case nameof(Single): case nameof(Decimal): builder.handler = dymMethod.CreateDelegate(typeof(Func <object, double>)); break; default: iString = true; builder.handler = dymMethod.CreateDelegate(typeof(Func <object, string>)); break; } return(builder); }