using FastMember; using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks; namespace HKW.HKWUtils; public static class ReflectionUtils { private static readonly BindingFlags _propertyBindingFlags = BindingFlags.Instance | BindingFlags.Public; private static readonly Dictionary _reflectionConverters = new(); /// /// 类型信息 /// /// (TargetType, (PropertyName, TargetPropertyName)) /// /// private static readonly Dictionary _typePropertyReflectionInfos = new(); public static void SetValue(object source, object target, ReflectionOptions options = null!) { options ??= new(); var sourceType = source.GetType(); var targetType = target.GetType(); if (_typePropertyReflectionInfos.TryGetValue(sourceType, out var sourceInfo) is false) sourceInfo = _typePropertyReflectionInfos[sourceType] = GetReflectionObjectInfo( sourceType ); if (_typePropertyReflectionInfos.TryGetValue(targetType, out var targetInfo) is false) targetInfo = _typePropertyReflectionInfos[targetType] = GetReflectionObjectInfo( targetType ); var sourceAccessor = ObjectAccessor.Create(source); var targetAccessor = ObjectAccessor.Create(target); foreach (var property in targetType.GetProperties(_propertyBindingFlags)) { // 尝试获取目标属性信息 targetInfo.PropertyInfos.TryGetValue(property.Name, out var targetReflectionInfo); // 检测忽视 if (targetReflectionInfo?.IsIgnore is true) continue; // 获取源属性名 var sourcePropertyName = targetReflectionInfo is null ? property.Name : targetReflectionInfo.TargetName; // 获取源属性信息 sourceInfo.PropertyInfos.TryGetValue(sourcePropertyName, out var sourceReflectionInfo); if (sourceInfo.PropertyNames.Contains(sourcePropertyName) is false) { if (targetReflectionInfo?.IsRequired is true) options.UnassignedRequiredProperties.Add(property.Name); continue; } // 获取源值 var sourceValue = sourceAccessor[sourcePropertyName]; // 转换源值 if (sourceReflectionInfo?.Converter is IReflectionConverter sourceConverter) sourceValue = sourceConverter.Convert(sourceValue); else if (targetReflectionInfo?.Converter is IReflectionConverter targetConverter) sourceValue = targetConverter.ConvertBack(sourceValue); // 比较源值和目标值 if (options.CheckValueEquals) { var targetValue = targetAccessor[property.Name]; if (sourceValue.Equals(targetValue)) continue; } targetAccessor[property.Name] = sourceValue; } } private static ReflectionObjectInfo GetReflectionObjectInfo(Type type) { var objectInfo = new ReflectionObjectInfo(type); foreach (var property in type.GetProperties(_propertyBindingFlags)) { // 获取是否被忽视 if (property.IsDefined(typeof(ReflectionPropertyIgnoreAttribute))) { objectInfo.PropertyInfos[property.Name] = new(property.Name) { IsIgnore = true }; continue; } if ( property.IsDefined(typeof(ReflectionPropertyIgnoreAttribute)) && property.IsDefined(typeof(ReflectionPropertyConverterAttribute)) is false ) continue; var propertyInfo = new ReflectionPropertyInfo(property.Name); // 获取属性信息 if ( property.GetCustomAttribute() is ReflectionPropertyAttribute propertyInfoAttribute ) { if (string.IsNullOrWhiteSpace(propertyInfoAttribute.TargetPropertyName) is false) propertyInfo.TargetName = propertyInfoAttribute.TargetPropertyName; propertyInfo.IsRequired = propertyInfoAttribute.IsRequired; } // 获取属性转换器 if ( property.GetCustomAttribute() is ReflectionPropertyConverterAttribute propertyConverterAttribute ) { if ( _reflectionConverters.TryGetValue( propertyConverterAttribute.ConverterType, out var converter ) is false ) converter = _reflectionConverters[propertyConverterAttribute.ConverterType] = (IReflectionConverter) TypeAccessor .Create(propertyConverterAttribute.ConverterType) .CreateNew(); propertyInfo.Converter = converter; } objectInfo.PropertyInfos[property.Name] = propertyInfo; } return objectInfo; } } /// /// 反射对象信息 /// public class ReflectionObjectInfo { public HashSet PropertyNames { get; } public Dictionary PropertyInfos { get; } = new(); public ReflectionObjectInfo(Type type) { PropertyNames = new( type.GetProperties(BindingFlags.Instance | BindingFlags.Public).Select(p => p.Name) ); } } public class ReflectionPropertyInfo { /// /// 目标属性名称 /// public string TargetName { get; set; } /// /// 是必要的 /// [DefaultValue(false)] public bool IsRequired { get; set; } = false; /// /// 是忽视的 /// public bool IsIgnore { get; set; } = false; /// /// 反射值转换器 /// public IReflectionConverter? Converter { get; set; } = null; public ReflectionPropertyInfo(string propertyName) { TargetName = propertyName; } } /// /// 反射属性信息 /// [AttributeUsage(AttributeTargets.Property)] public class ReflectionPropertyAttribute : Attribute { /// /// 属性名称 /// public string TargetPropertyName { get; } /// /// 是必要的 /// [DefaultValue(true)] public bool IsRequired { get; } = true; public ReflectionPropertyAttribute(bool isRequired = true) { IsRequired = isRequired; } public ReflectionPropertyAttribute(string targetPropertyName, bool isRequired = true) { TargetPropertyName = targetPropertyName; IsRequired = isRequired; } } /// /// 反射属性转换器 /// [AttributeUsage(AttributeTargets.Property)] public class ReflectionPropertyConverterAttribute : Attribute { /// /// 反射转换器 /// public Type ConverterType { get; } public ReflectionPropertyConverterAttribute(Type converterType) { ConverterType = converterType; } } /// /// 反射属性忽视 /// [AttributeUsage(AttributeTargets.Property)] public class ReflectionPropertyIgnoreAttribute : Attribute { public ReflectionPropertyIgnoreAttribute() { } } /// /// 反射设置 /// public class ReflectionOptions { /// /// 检查值是否相等, 若相等则跳过赋值 /// [DefaultValue(false)] public bool CheckValueEquals { get; set; } = false; /// /// 未赋值的必要属性 /// public List UnassignedRequiredProperties { get; set; } = new(); } /// /// 反射转换器 /// public interface IReflectionConverter { public object Convert(object sourceValue); public object ConvertBack(object targetValue); } /// /// 反射转换器 /// /// 源值类型 /// 目标值类型 public abstract class ReflectionConverterBase : IReflectionConverter { public abstract TTarget Convert(TSource sourceValue); public abstract TSource ConvertBack(TTarget targetValue); object IReflectionConverter.Convert(object sourceValue) { return Convert((TSource)sourceValue); } object IReflectionConverter.ConvertBack(object targetValue) { return ConvertBack((TTarget)targetValue); } }