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-04-02 23:54:56 +08:00
|
|
|
|
var (itemType, propType, dataIndex) = key;
|
2021-01-20 23:35:57 +08:00
|
|
|
|
Func<RowData, TProp> getValue = null;
|
2021-04-02 23:54:56 +08:00
|
|
|
|
LambdaExpression getFieldExpression = null;
|
2021-01-20 23:35:57 +08:00
|
|
|
|
var properties = dataIndex?.Split(".");
|
2021-01-31 01:25:25 +08:00
|
|
|
|
if (properties is {Length: > 0})
|
2021-01-20 23:35:57 +08:00
|
|
|
|
{
|
2021-01-31 01:25:25 +08:00
|
|
|
|
var canBeNull = !propType.IsValueType || Nullable.GetUnderlyingType(propType) != null;
|
2021-01-20 23:35:57 +08:00
|
|
|
|
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));
|
|
|
|
|
|
2021-04-02 23:54:56 +08:00
|
|
|
|
var memberExp = canBeNull
|
|
|
|
|
? dataMemberExp.AccessNullableProperty(properties)
|
|
|
|
|
: dataMemberExp.AccessProperty(properties);
|
2021-01-20 23:35:57 +08:00
|
|
|
|
getValue = Expression.Lambda<Func<RowData, TProp>>(memberExp, rowDataExp).Compile();
|
|
|
|
|
|
2021-04-02 23:54:56 +08:00
|
|
|
|
getFieldExpression = canBeNull
|
|
|
|
|
? itemType.BuildAccessNullablePropertyLambdaExpression(properties)
|
|
|
|
|
: itemType.BuildAccessPropertyLambdaExpression(properties);
|
2021-01-20 23:35:57 +08:00
|
|
|
|
}
|
|
|
|
|
|
2021-04-02 23:54:56 +08:00
|
|
|
|
return new ColumnCacheItem(getValue, getFieldExpression);
|
2021-01-20 23:35:57 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
internal readonly struct ColumnCacheKey
|
|
|
|
|
{
|
|
|
|
|
internal readonly Type ItemType;
|
|
|
|
|
|
|
|
|
|
internal readonly Type PropType;
|
|
|
|
|
|
|
|
|
|
internal readonly string DataIndex;
|
|
|
|
|
|
|
|
|
|
internal static ColumnCacheKey Create(Column<TProp> column)
|
|
|
|
|
{
|
2021-04-02 23:54:56 +08:00
|
|
|
|
return new(column.ItemType, typeof(TProp), column.DataIndex);
|
2021-01-20 23:35:57 +08:00
|
|
|
|
}
|
|
|
|
|
|
2021-04-02 23:54:56 +08:00
|
|
|
|
internal ColumnCacheKey(Type itemType, Type propType, string dataIndex)
|
2021-01-20 23:35:57 +08:00
|
|
|
|
{
|
|
|
|
|
ItemType = itemType;
|
|
|
|
|
PropType = propType;
|
|
|
|
|
DataIndex = dataIndex;
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-02 23:54:56 +08:00
|
|
|
|
internal void Deconstruct(out Type itemType, out Type propType, out string dataIndex)
|
2021-01-20 23:35:57 +08:00
|
|
|
|
{
|
|
|
|
|
itemType = ItemType;
|
|
|
|
|
propType = PropType;
|
|
|
|
|
dataIndex = DataIndex;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
internal readonly struct ColumnCacheItem
|
|
|
|
|
{
|
|
|
|
|
internal readonly Func<RowData, TProp> GetValue;
|
|
|
|
|
|
2021-04-02 23:54:56 +08:00
|
|
|
|
internal readonly LambdaExpression GetFieldExpression;
|
2021-01-20 23:35:57 +08:00
|
|
|
|
|
2021-04-02 23:54:56 +08:00
|
|
|
|
internal ColumnCacheItem(Func<RowData, TProp> getValue, LambdaExpression getFieldExpression)
|
2021-01-20 23:35:57 +08:00
|
|
|
|
{
|
|
|
|
|
GetValue = getValue;
|
2021-04-02 23:54:56 +08:00
|
|
|
|
GetFieldExpression = getFieldExpression;
|
2021-01-20 23:35:57 +08:00
|
|
|
|
}
|
|
|
|
|
|
2021-04-02 23:54:56 +08:00
|
|
|
|
internal void Deconstruct(out Func<RowData, TProp> getValue, out LambdaExpression getFieldExpression)
|
2021-01-20 23:35:57 +08:00
|
|
|
|
{
|
|
|
|
|
getValue = GetValue;
|
2021-04-02 23:54:56 +08:00
|
|
|
|
getFieldExpression = GetFieldExpression;
|
2021-01-20 23:35:57 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|