Skip to content

Commit

Permalink
feat(Sort): Sort extension method support IDynamicObject (#4726)
Browse files Browse the repository at this point in the history
* feat: 增加 CastAndOrder 方法

* test: 更新单元测试

* chore: bump version 9.0.2-beta01
  • Loading branch information
ArgoZhang authored Nov 23, 2024
1 parent d0c4d9a commit 227fa5e
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 9 deletions.
2 changes: 1 addition & 1 deletion src/BootstrapBlazor/BootstrapBlazor.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk.Razor">

<PropertyGroup>
<Version>9.0.1</Version>
<Version>9.0.2-beta01</Version>
</PropertyGroup>

<ItemGroup>
Expand Down
47 changes: 39 additions & 8 deletions src/BootstrapBlazor/Extensions/LambdaExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -449,12 +449,24 @@ private static IEnumerable<TItem> EnumerableOrderBy<TItem>(IEnumerable<TItem> qu

IEnumerable<TItem> EnumerableOrderBySimple()
{
var type = typeof(TItem);
IEnumerable<TItem>? ret = null;
var pi = typeof(TItem).GetPropertyByName(propertyName);
if (pi != null)
if (type.IsInterface && type == typeof(IDynamicObject))
{
var methodName = sortOrder == SortOrder.Desc ? nameof(OrderByDescendingInternal) : nameof(OrderByInternal);
ret = query.AsQueryable().InvokeSortByPropertyInfo(methodName, pi);
var instance = query.FirstOrDefault();
if (instance != null)
{
ret = CastAndOrder(query, instance.GetType(), propertyName, sortOrder);
}
}
else
{
var pi = type.GetPropertyByName(propertyName);
if (pi != null)
{
var methodName = sortOrder == SortOrder.Desc ? nameof(OrderByDescendingInternal) : nameof(OrderByInternal);
ret = query.AsQueryable().InvokeSortByPropertyInfo(methodName, pi);
}
}
return ret ?? query;
}
Expand All @@ -476,6 +488,25 @@ IEnumerable<TItem> EnumerableOrderByComplex()
}
}

private static IEnumerable<TItem>? CastAndOrder<TItem>(IEnumerable<TItem> query, Type propertyType, string propertyName, SortOrder sortOrder)
{
IEnumerable<TItem>? ret = null;
var castMethod = typeof(Enumerable).GetMethod(nameof(Enumerable.Cast), BindingFlags.Static | BindingFlags.Public);
if (castMethod != null)
{
var mi = castMethod.MakeGenericMethod(propertyType);
var collection = mi.Invoke(null, [query]);

var orderMethod = typeof(LambdaExtensions).GetMethod(nameof(EnumerableOrderBy), BindingFlags.Static | BindingFlags.NonPublic);
if (orderMethod != null)
{
var miOrder = orderMethod.MakeGenericMethod(propertyType);
ret = miOrder.Invoke(null, [collection, propertyName, sortOrder]) as IEnumerable<TItem>;
}
}
return ret;
}

private static IEnumerable<TItem> EnumerableThenBy<TItem>(IEnumerable<TItem> query, string propertyName, SortOrder sortOrder)
{
return propertyName.Contains('.') ? EnumerableThenByComplex() : EnumerableThenBySimple();
Expand Down Expand Up @@ -583,13 +614,13 @@ IQueryable<TItem> QueryableThenByComplex()

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

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

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

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

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

private static Expression<Func<TItem, TKey>> GetPropertyLambda<TItem, TKey>(PropertyInfo pi)
{
Expand Down
57 changes: 57 additions & 0 deletions test/UnitTest/Extensions/LambadaExtensionsTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
// Maintainer: Argo Zhang(argo@live.ca) Website: https://www.blazor.zone

using System.ComponentModel.DataAnnotations;
using System.Data;
using System.Dynamic;
using System.Linq.Expressions;

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

[Fact]
public void Sort_IDynamicObject_Ok()
{
var dataTable = new DataTable();

DataColumn column = new DataColumn
{
DataType = Type.GetType("System.Int32"),
ColumnName = "ID"
};
dataTable.Columns.Add(column);

column = new DataColumn
{
DataType = Type.GetType("System.String"),
ColumnName = "Name"
};
dataTable.Columns.Add(column);

//Creating some rows
DataRow row = dataTable.NewRow();
row["ID"] = 1;
row["Name"] = "Bob";
dataTable.Rows.Add(row);

row = dataTable.NewRow();
row["ID"] = 3;
row["Name"] = "Adam";
dataTable.Rows.Add(row);

row = dataTable.NewRow();
row["ID"] = 2;
row["Name"] = "Jane";
dataTable.Rows.Add(row);

var context = new DataTableDynamicContext(dataTable, (context, col) => { });
var items = context.GetItems().ToList();

// 未排序
Assert.Equal("Bob", items[0].GetValue("Name"));
Assert.Equal("Adam", items[1].GetValue("Name"));
Assert.Equal("Jane", items[2].GetValue("Name"));

// Name 排序
var nameItems = items.Sort("Name", SortOrder.Asc).ToList();
Assert.Equal("Adam", nameItems[0].GetValue("Name"));
Assert.Equal("Bob", nameItems[1].GetValue("Name"));
Assert.Equal("Jane", nameItems[2].GetValue("Name"));

// Name 倒序
nameItems = items.Sort("Name", SortOrder.Desc).ToList();
Assert.Equal("Adam", nameItems[2].GetValue("Name"));
Assert.Equal("Bob", nameItems[1].GetValue("Name"));
Assert.Equal("Jane", nameItems[0].GetValue("Name"));
}

[Fact]
public void GetPropertyValueLambda_Null()
{
Expand Down

0 comments on commit 227fa5e

Please sign in to comment.