2021-01-20 23:35:57 +08:00
|
|
|
|
// Licensed to the .NET Foundation under one or more agreements.
|
|
|
|
|
// The .NET Foundation licenses this file to you under the MIT license.
|
|
|
|
|
// See the LICENSE file in the project root for more information.
|
|
|
|
|
|
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Concurrent;
|
|
|
|
|
using System.Linq.Expressions;
|
|
|
|
|
using AntDesign.core.Helpers;
|
|
|
|
|
using AntDesign.TableModels;
|
|
|
|
|
|
|
|
|
|
namespace AntDesign.Internal
|
|
|
|
|
{
|
|
|
|
|
internal static class ColumnDataIndexHelper<TProp>
|
|
|
|
|
{
|
|
|
|
|
private static readonly ConcurrentDictionary<ColumnCacheKey, ColumnCacheItem> _dataIndexCache = new();
|
|
|
|
|
|
|
|
|
|
internal static ColumnCacheItem GetDataIndexConfig(Column<TProp> column)
|
|
|
|
|
{
|
|
|
|
|
if (column == null)
|
|
|
|
|
{
|
|
|
|
|
throw new ArgumentNullException(nameof(column));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var cacheKey = ColumnCacheKey.Create(column);
|
|
|
|
|
return _dataIndexCache.GetOrAdd(cacheKey, CreateDataIndexConfig);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static ColumnCacheItem CreateDataIndexConfig(ColumnCacheKey key)
|
|
|
|
|
{
|
2021-01-22 00:45:15 +08:00
|
|
|
|
var (itemType, propType, dataIndex, sortable, sort, sorterMultiple, sorterCompare) = key;
|
2021-01-20 23:35:57 +08:00
|
|
|
|
Func<RowData, TProp> getValue = null;
|
|
|
|
|
ITableSortModel sortModel = null;
|
|
|
|
|
var properties = dataIndex?.Split(".");
|
|
|
|
|
if (properties is { Length: > 0 })
|
|
|
|
|
{
|
|
|
|
|
var isNullable = propType.IsValueType && Nullable.GetUnderlyingType(propType) != null;
|
|
|
|
|
var rowDataType = typeof(RowData);
|
|
|
|
|
var rowData1Type = typeof(RowData<>).MakeGenericType(itemType);
|
|
|
|
|
var rowDataExp = Expression.Parameter(rowDataType);
|
|
|
|
|
var rowData1Exp = Expression.TypeAs(rowDataExp, rowData1Type);
|
|
|
|
|
var dataMemberExp = Expression.Property(rowData1Exp, nameof(RowData<object>.Data));
|
|
|
|
|
|
|
|
|
|
Expression memberExp = isNullable
|
|
|
|
|
? PropertyAccessHelper.AccessNullableProperty(dataMemberExp, properties)
|
|
|
|
|
: PropertyAccessHelper.AccessProperty(dataMemberExp, properties);
|
|
|
|
|
getValue = Expression.Lambda<Func<RowData, TProp>>(memberExp, rowDataExp).Compile();
|
|
|
|
|
|
|
|
|
|
if (sortable)
|
|
|
|
|
{
|
|
|
|
|
var propertySelector = isNullable
|
|
|
|
|
? PropertyAccessHelper.BuildNullablePropertyAccessExpression(itemType, properties)
|
|
|
|
|
: PropertyAccessHelper.BuildPropertyAccessExpression(itemType, properties);
|
2021-01-22 00:45:15 +08:00
|
|
|
|
sortModel = new DataIndexSortModel<TProp>(dataIndex, propertySelector, sorterMultiple, sort, sorterCompare);
|
2021-01-20 23:35:57 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return new ColumnCacheItem(getValue, sortModel);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
internal readonly struct ColumnCacheKey
|
|
|
|
|
{
|
|
|
|
|
internal readonly Type ItemType;
|
|
|
|
|
|
|
|
|
|
internal readonly Type PropType;
|
|
|
|
|
|
|
|
|
|
internal readonly string DataIndex;
|
|
|
|
|
|
|
|
|
|
internal readonly bool Sortable;
|
|
|
|
|
|
|
|
|
|
internal readonly string Sort;
|
|
|
|
|
|
2021-01-22 00:45:15 +08:00
|
|
|
|
internal readonly int SorterMultiple;
|
|
|
|
|
|
2021-01-20 23:35:57 +08:00
|
|
|
|
internal readonly Func<TProp, TProp, int> SorterCompare;
|
|
|
|
|
|
|
|
|
|
internal static ColumnCacheKey Create(Column<TProp> column)
|
|
|
|
|
{
|
2021-01-22 00:45:15 +08:00
|
|
|
|
return new(column.ItemType, typeof(TProp), column.DataIndex, column.Sortable, column.Sort, column.SorterMultiple, column.SorterCompare);
|
2021-01-20 23:35:57 +08:00
|
|
|
|
}
|
|
|
|
|
|
2021-01-22 00:45:15 +08:00
|
|
|
|
internal ColumnCacheKey(Type itemType, Type propType, string dataIndex, bool sortable, string sort, int sorterMultiple, Func<TProp, TProp, int> sorterCompare)
|
2021-01-20 23:35:57 +08:00
|
|
|
|
{
|
|
|
|
|
ItemType = itemType;
|
|
|
|
|
PropType = propType;
|
|
|
|
|
DataIndex = dataIndex;
|
|
|
|
|
Sortable = sortable;
|
|
|
|
|
Sort = sort;
|
2021-01-22 00:45:15 +08:00
|
|
|
|
SorterMultiple = sorterMultiple;
|
2021-01-20 23:35:57 +08:00
|
|
|
|
SorterCompare = sorterCompare;
|
|
|
|
|
}
|
|
|
|
|
|
2021-01-22 00:45:15 +08:00
|
|
|
|
internal void Deconstruct(out Type itemType, out Type propType, out string dataIndex, out bool sortable, out string sort, out int sorterMultiple, out Func<TProp, TProp, int> sorterCompare)
|
2021-01-20 23:35:57 +08:00
|
|
|
|
{
|
|
|
|
|
itemType = ItemType;
|
|
|
|
|
propType = PropType;
|
|
|
|
|
dataIndex = DataIndex;
|
|
|
|
|
sortable = Sortable;
|
|
|
|
|
sort = Sort;
|
2021-01-22 00:45:15 +08:00
|
|
|
|
sorterMultiple = SorterMultiple;
|
2021-01-20 23:35:57 +08:00
|
|
|
|
sorterCompare = SorterCompare;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
internal readonly struct ColumnCacheItem
|
|
|
|
|
{
|
|
|
|
|
internal readonly Func<RowData, TProp> GetValue;
|
|
|
|
|
|
|
|
|
|
internal readonly ITableSortModel SortModel;
|
|
|
|
|
|
|
|
|
|
internal ColumnCacheItem(Func<RowData, TProp> getValue, ITableSortModel sortModel)
|
|
|
|
|
{
|
|
|
|
|
GetValue = getValue;
|
|
|
|
|
SortModel = sortModel;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
internal void Deconstruct(out Func<RowData, TProp> getValue, out ITableSortModel sortModel)
|
|
|
|
|
{
|
|
|
|
|
getValue = GetValue;
|
|
|
|
|
sortModel = SortModel;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|