2021-07-26 13:16:19 +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;
|
2021-05-08 13:00:52 +08:00
|
|
|
|
using System.Collections.Generic;
|
2021-07-26 13:16:19 +08:00
|
|
|
|
using System.ComponentModel.DataAnnotations;
|
2021-05-08 13:00:52 +08:00
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Linq.Expressions;
|
2021-07-26 13:16:19 +08:00
|
|
|
|
using System.Reflection;
|
2021-05-08 13:00:52 +08:00
|
|
|
|
|
|
|
|
|
namespace AntDesign
|
|
|
|
|
{
|
|
|
|
|
public static class EnumHelper<T>
|
|
|
|
|
{
|
2024-05-07 00:49:18 +08:00
|
|
|
|
private static readonly MethodInfo _enumHasFlag = typeof(Enum).GetMethod(nameof(Enum.HasFlag));
|
|
|
|
|
|
2021-05-08 13:00:52 +08:00
|
|
|
|
private static readonly Func<T, T, T> _aggregateFunction;
|
2024-05-07 00:49:18 +08:00
|
|
|
|
private static readonly Func<T, T, bool> _hasFlagFunction;
|
2021-05-08 13:00:52 +08:00
|
|
|
|
|
2022-10-21 13:01:25 +08:00
|
|
|
|
private static readonly IEnumerable<T> _valueList;
|
|
|
|
|
private static readonly IEnumerable<(T Value, string Label)> _valueLabelList;
|
|
|
|
|
private static readonly Type _enumType;
|
2024-05-07 00:49:18 +08:00
|
|
|
|
private static readonly bool _isFlags;
|
|
|
|
|
|
|
|
|
|
public static bool IsFlags => _isFlags;
|
2021-07-27 13:43:23 +08:00
|
|
|
|
|
2021-05-08 13:00:52 +08:00
|
|
|
|
static EnumHelper()
|
|
|
|
|
{
|
2021-07-27 13:43:23 +08:00
|
|
|
|
_enumType = THelper.GetUnderlyingType<T>();
|
2021-05-08 13:00:52 +08:00
|
|
|
|
_aggregateFunction = BuildAggregateFunction();
|
2021-07-27 13:43:23 +08:00
|
|
|
|
_valueList = Enum.GetValues(_enumType).Cast<T>();
|
2021-08-15 00:27:41 +08:00
|
|
|
|
_valueLabelList = _valueList.Select(value => (value, GetDisplayName(value)));
|
2024-05-07 00:49:18 +08:00
|
|
|
|
_isFlags = _enumType.GetCustomAttribute<FlagsAttribute>() != null;
|
|
|
|
|
_hasFlagFunction = BuildHasFlagFunction();
|
2021-05-08 13:00:52 +08:00
|
|
|
|
}
|
|
|
|
|
|
2022-10-21 13:01:25 +08:00
|
|
|
|
// There is no constraint or type check for type parameter T, be sure that T is an enumeration type
|
2021-06-03 18:54:41 +08:00
|
|
|
|
public static object Combine(IEnumerable<T> enumValues)
|
2021-05-08 13:00:52 +08:00
|
|
|
|
{
|
2022-10-21 13:01:25 +08:00
|
|
|
|
if (enumValues?.Any() == true)
|
2021-05-08 13:00:52 +08:00
|
|
|
|
{
|
|
|
|
|
return enumValues.Aggregate(_aggregateFunction);
|
|
|
|
|
}
|
2024-05-09 23:14:57 +08:00
|
|
|
|
return default(T);
|
2021-05-08 13:00:52 +08:00
|
|
|
|
}
|
|
|
|
|
|
2021-07-27 13:43:23 +08:00
|
|
|
|
public static IEnumerable<T> Split(object enumValue)
|
|
|
|
|
{
|
2024-05-07 00:49:18 +08:00
|
|
|
|
if (enumValue == null)
|
2022-10-21 13:01:25 +08:00
|
|
|
|
{
|
|
|
|
|
return Array.Empty<T>();
|
|
|
|
|
}
|
2024-05-07 00:49:18 +08:00
|
|
|
|
if (enumValue is string enumString)
|
|
|
|
|
{
|
|
|
|
|
return _valueList.Where(value => enumString.Split(",").Contains(Enum.GetName(_enumType, value)));
|
|
|
|
|
}
|
|
|
|
|
return _valueList.Where(value => _hasFlagFunction((T)enumValue, value));
|
2021-07-27 13:43:23 +08:00
|
|
|
|
}
|
|
|
|
|
|
2021-07-26 13:16:19 +08:00
|
|
|
|
public static IEnumerable<T> GetValueList()
|
|
|
|
|
{
|
|
|
|
|
return _valueList;
|
|
|
|
|
}
|
|
|
|
|
|
2021-08-15 00:27:41 +08:00
|
|
|
|
public static IEnumerable<(T Value, string Label)> GetValueLabelList()
|
|
|
|
|
{
|
|
|
|
|
return _valueLabelList;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static string GetDisplayName(T enumValue)
|
2021-07-26 13:16:19 +08:00
|
|
|
|
{
|
2021-08-15 00:27:41 +08:00
|
|
|
|
var enumName = Enum.GetName(_enumType, enumValue);
|
|
|
|
|
var fieldInfo = _enumType.GetField(enumName);
|
2023-12-01 00:30:45 +08:00
|
|
|
|
return fieldInfo.GetCustomAttribute<DisplayAttribute>(true)?.GetName() ?? enumName;
|
2021-07-26 13:16:19 +08:00
|
|
|
|
}
|
|
|
|
|
|
2021-05-08 13:00:52 +08:00
|
|
|
|
private static Func<T, T, T> BuildAggregateFunction()
|
|
|
|
|
{
|
|
|
|
|
var type = typeof(T);
|
2021-07-27 13:43:23 +08:00
|
|
|
|
var underlyingType = Enum.GetUnderlyingType(_enumType);
|
2021-05-08 13:00:52 +08:00
|
|
|
|
var param1 = Expression.Parameter(type);
|
|
|
|
|
var param2 = Expression.Parameter(type);
|
|
|
|
|
var body = Expression.Convert(
|
|
|
|
|
Expression.Or(
|
|
|
|
|
Expression.Convert(param1, underlyingType),
|
|
|
|
|
Expression.Convert(param2, underlyingType)),
|
|
|
|
|
type);
|
|
|
|
|
return Expression.Lambda<Func<T, T, T>>(body, param1, param2).Compile();
|
|
|
|
|
}
|
2024-05-07 00:49:18 +08:00
|
|
|
|
|
|
|
|
|
private static Func<T, T, bool> BuildHasFlagFunction()
|
|
|
|
|
{
|
|
|
|
|
var type = typeof(T);
|
|
|
|
|
var param1 = Expression.Parameter(type);
|
|
|
|
|
var param2 = Expression.Parameter(type);
|
2024-05-12 13:02:27 +08:00
|
|
|
|
|
|
|
|
|
if (THelper.IsTypeNullable(type))
|
|
|
|
|
{
|
|
|
|
|
Expression notNull = Expression.NotEqual(param1, Expression.Constant(null));
|
|
|
|
|
var param1Value = Expression.MakeMemberAccess(param1, param1.Type.GetMember(nameof(Nullable<int>.Value))[0]);
|
|
|
|
|
var param1ValueHasFlags = Expression.Call(param1Value, _enumHasFlag, Expression.Convert(param2, typeof(Enum)));
|
|
|
|
|
var notNullAndParam1ValueHasFlags = Expression.AndAlso(notNull, param1ValueHasFlags);
|
|
|
|
|
|
|
|
|
|
return Expression.Lambda<Func<T, T, bool>>(notNullAndParam1ValueHasFlags, param1, param2).Compile();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
var body = Expression.Call(param1, _enumHasFlag, Expression.Convert(param2, typeof(Enum)));
|
|
|
|
|
return Expression.Lambda<Func<T, T, bool>>(body, param1, param2).Compile();
|
|
|
|
|
}
|
2024-05-07 00:49:18 +08:00
|
|
|
|
}
|
2021-05-08 13:00:52 +08:00
|
|
|
|
}
|
|
|
|
|
}
|