Skip to content

Commit 227fa5e

Browse files
authored
feat(Sort): Sort extension method support IDynamicObject (#4726)
* feat: 增加 CastAndOrder 方法 * test: 更新单元测试 * chore: bump version 9.0.2-beta01
1 parent d0c4d9a commit 227fa5e

File tree

3 files changed

+97
-9
lines changed

3 files changed

+97
-9
lines changed

src/BootstrapBlazor/BootstrapBlazor.csproj

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<Project Sdk="Microsoft.NET.Sdk.Razor">
22

33
<PropertyGroup>
4-
<Version>9.0.1</Version>
4+
<Version>9.0.2-beta01</Version>
55
</PropertyGroup>
66

77
<ItemGroup>

src/BootstrapBlazor/Extensions/LambdaExtensions.cs

+39-8
Original file line numberDiff line numberDiff line change
@@ -449,12 +449,24 @@ private static IEnumerable<TItem> EnumerableOrderBy<TItem>(IEnumerable<TItem> qu
449449

450450
IEnumerable<TItem> EnumerableOrderBySimple()
451451
{
452+
var type = typeof(TItem);
452453
IEnumerable<TItem>? ret = null;
453-
var pi = typeof(TItem).GetPropertyByName(propertyName);
454-
if (pi != null)
454+
if (type.IsInterface && type == typeof(IDynamicObject))
455455
{
456-
var methodName = sortOrder == SortOrder.Desc ? nameof(OrderByDescendingInternal) : nameof(OrderByInternal);
457-
ret = query.AsQueryable().InvokeSortByPropertyInfo(methodName, pi);
456+
var instance = query.FirstOrDefault();
457+
if (instance != null)
458+
{
459+
ret = CastAndOrder(query, instance.GetType(), propertyName, sortOrder);
460+
}
461+
}
462+
else
463+
{
464+
var pi = type.GetPropertyByName(propertyName);
465+
if (pi != null)
466+
{
467+
var methodName = sortOrder == SortOrder.Desc ? nameof(OrderByDescendingInternal) : nameof(OrderByInternal);
468+
ret = query.AsQueryable().InvokeSortByPropertyInfo(methodName, pi);
469+
}
458470
}
459471
return ret ?? query;
460472
}
@@ -476,6 +488,25 @@ IEnumerable<TItem> EnumerableOrderByComplex()
476488
}
477489
}
478490

491+
private static IEnumerable<TItem>? CastAndOrder<TItem>(IEnumerable<TItem> query, Type propertyType, string propertyName, SortOrder sortOrder)
492+
{
493+
IEnumerable<TItem>? ret = null;
494+
var castMethod = typeof(Enumerable).GetMethod(nameof(Enumerable.Cast), BindingFlags.Static | BindingFlags.Public);
495+
if (castMethod != null)
496+
{
497+
var mi = castMethod.MakeGenericMethod(propertyType);
498+
var collection = mi.Invoke(null, [query]);
499+
500+
var orderMethod = typeof(LambdaExtensions).GetMethod(nameof(EnumerableOrderBy), BindingFlags.Static | BindingFlags.NonPublic);
501+
if (orderMethod != null)
502+
{
503+
var miOrder = orderMethod.MakeGenericMethod(propertyType);
504+
ret = miOrder.Invoke(null, [collection, propertyName, sortOrder]) as IEnumerable<TItem>;
505+
}
506+
}
507+
return ret;
508+
}
509+
479510
private static IEnumerable<TItem> EnumerableThenBy<TItem>(IEnumerable<TItem> query, string propertyName, SortOrder sortOrder)
480511
{
481512
return propertyName.Contains('.') ? EnumerableThenByComplex() : EnumerableThenBySimple();
@@ -583,13 +614,13 @@ IQueryable<TItem> QueryableThenByComplex()
583614

584615
private static IOrderedQueryable<TItem> ThenByDescendingInternalByName<TItem, TKey>(IOrderedQueryable<TItem> query, string propertyName) => query.ThenByDescending(GetPropertyLambdaByName<TItem, TKey>(propertyName));
585616

586-
private static IOrderedQueryable<TItem> OrderByInternal<TItem, TKey>(IQueryable<TItem> query, System.Reflection.PropertyInfo memberProperty) => query.OrderBy(GetPropertyLambda<TItem, TKey>(memberProperty));
617+
private static IOrderedQueryable<TItem> OrderByInternal<TItem, TKey>(IQueryable<TItem> query, PropertyInfo memberProperty) => query.OrderBy(GetPropertyLambda<TItem, TKey>(memberProperty));
587618

588-
private static IOrderedQueryable<TItem> OrderByDescendingInternal<TItem, TKey>(IQueryable<TItem> query, System.Reflection.PropertyInfo memberProperty) => query.OrderByDescending(GetPropertyLambda<TItem, TKey>(memberProperty));
619+
private static IOrderedQueryable<TItem> OrderByDescendingInternal<TItem, TKey>(IQueryable<TItem> query, PropertyInfo memberProperty) => query.OrderByDescending(GetPropertyLambda<TItem, TKey>(memberProperty));
589620

590-
private static IOrderedQueryable<TItem> ThenByInternal<TItem, TKey>(IOrderedQueryable<TItem> query, System.Reflection.PropertyInfo memberProperty) => query.ThenBy(GetPropertyLambda<TItem, TKey>(memberProperty));
621+
private static IOrderedQueryable<TItem> ThenByInternal<TItem, TKey>(IOrderedQueryable<TItem> query, PropertyInfo memberProperty) => query.ThenBy(GetPropertyLambda<TItem, TKey>(memberProperty));
591622

592-
private static IOrderedQueryable<TItem> ThenByDescendingInternal<TItem, TKey>(IOrderedQueryable<TItem> query, System.Reflection.PropertyInfo memberProperty) => query.ThenByDescending(GetPropertyLambda<TItem, TKey>(memberProperty));
623+
private static IOrderedQueryable<TItem> ThenByDescendingInternal<TItem, TKey>(IOrderedQueryable<TItem> query, PropertyInfo memberProperty) => query.ThenByDescending(GetPropertyLambda<TItem, TKey>(memberProperty));
593624

594625
private static Expression<Func<TItem, TKey>> GetPropertyLambda<TItem, TKey>(PropertyInfo pi)
595626
{

test/UnitTest/Extensions/LambadaExtensionsTest.cs

+57
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
// Maintainer: Argo Zhang(argo@live.ca) Website: https://www.blazor.zone
55

66
using System.ComponentModel.DataAnnotations;
7+
using System.Data;
78
using System.Dynamic;
89
using System.Linq.Expressions;
910

@@ -416,6 +417,62 @@ public void Sort_Queryable_Complex()
416417
Assert.Equal(10, orderFoos.ElementAt(0).Foo!.Count);
417418
}
418419

420+
[Fact]
421+
public void Sort_IDynamicObject_Ok()
422+
{
423+
var dataTable = new DataTable();
424+
425+
DataColumn column = new DataColumn
426+
{
427+
DataType = Type.GetType("System.Int32"),
428+
ColumnName = "ID"
429+
};
430+
dataTable.Columns.Add(column);
431+
432+
column = new DataColumn
433+
{
434+
DataType = Type.GetType("System.String"),
435+
ColumnName = "Name"
436+
};
437+
dataTable.Columns.Add(column);
438+
439+
//Creating some rows
440+
DataRow row = dataTable.NewRow();
441+
row["ID"] = 1;
442+
row["Name"] = "Bob";
443+
dataTable.Rows.Add(row);
444+
445+
row = dataTable.NewRow();
446+
row["ID"] = 3;
447+
row["Name"] = "Adam";
448+
dataTable.Rows.Add(row);
449+
450+
row = dataTable.NewRow();
451+
row["ID"] = 2;
452+
row["Name"] = "Jane";
453+
dataTable.Rows.Add(row);
454+
455+
var context = new DataTableDynamicContext(dataTable, (context, col) => { });
456+
var items = context.GetItems().ToList();
457+
458+
// 未排序
459+
Assert.Equal("Bob", items[0].GetValue("Name"));
460+
Assert.Equal("Adam", items[1].GetValue("Name"));
461+
Assert.Equal("Jane", items[2].GetValue("Name"));
462+
463+
// Name 排序
464+
var nameItems = items.Sort("Name", SortOrder.Asc).ToList();
465+
Assert.Equal("Adam", nameItems[0].GetValue("Name"));
466+
Assert.Equal("Bob", nameItems[1].GetValue("Name"));
467+
Assert.Equal("Jane", nameItems[2].GetValue("Name"));
468+
469+
// Name 倒序
470+
nameItems = items.Sort("Name", SortOrder.Desc).ToList();
471+
Assert.Equal("Adam", nameItems[2].GetValue("Name"));
472+
Assert.Equal("Bob", nameItems[1].GetValue("Name"));
473+
Assert.Equal("Jane", nameItems[0].GetValue("Name"));
474+
}
475+
419476
[Fact]
420477
public void GetPropertyValueLambda_Null()
421478
{

0 commit comments

Comments
 (0)