using System; using System.Linq; using System.Linq.Expressions; using System.Reflection; using Microsoft.AspNetCore.Components; namespace AntDesign.Core.HashCodes { /// /// Represents a parameter descriptor for a component /// /// class ParameterDescriptor { private readonly bool _isParameter; private readonly HashCodeProvider _hashCodeProvider; private readonly Func _getter; /// /// Gets a description of all the parameters of the component /// public static readonly ParameterDescriptor[] Descriptors = typeof(TComponent) .GetProperties() .Select(item => new ParameterDescriptor(item)) .Where(item => item._isParameter) .ToArray(); /// /// A parameter descriptor for a component /// /// 属性类型 private ParameterDescriptor(PropertyInfo property) { if (property == null) { throw new ArgumentNullException(nameof(property)); } this._isParameter = IsEventCallBack(property) == false || property.IsDefined(typeof(ParameterAttribute)) || property.IsDefined(typeof(CascadingParameterAttribute)); if (this._isParameter == true) { this._getter = CreateGetFunc(property); this._hashCodeProvider = HashCodeProvider.Create(property.PropertyType); } } /// /// Check whether it is of type EventCallback /// /// /// private static bool IsEventCallBack(PropertyInfo property) { var type = property.PropertyType; if (type == typeof(EventCallback)) { return true; } if (type.IsGenericType == true) { return type.GetGenericTypeDefinition() == typeof(EventCallback<>); } return false; } /// /// Create the get delegate for the property /// /// Property /// private static Func CreateGetFunc(PropertyInfo property) { // (TComponent component) => (object)(component.Property) var componentType = typeof(TComponent); var parameter = Expression.Parameter(componentType); var member = Expression.Property(parameter, property); var body = Expression.Convert(member, typeof(object)); return Expression.Lambda>(body, parameter).Compile(); } /// /// Returns the hash of the parameter value /// /// 组件 /// /// public int GetValueHashCode(TComponent component) { if (this._isParameter == false) { throw new NotSupportedException(); } var value = this._getter(component); return this._hashCodeProvider.GetHashCode(value); } } }