VPet/VPet.Solution/Utils/ReflectionUtils.cs

284 lines
8.9 KiB
C#
Raw Normal View History

2024-01-10 13:37:17 +00:00
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
{
2024-01-11 16:28:22 +00:00
private static readonly BindingFlags _propertyBindingFlags =
BindingFlags.Instance | BindingFlags.Public;
2024-01-12 14:17:50 +00:00
private static readonly Dictionary<Type, IReflectionConverter> _reflectionConverters = new();
2024-01-10 13:37:17 +00:00
/// <summary>
2024-01-11 16:28:22 +00:00
/// 类型信息
2024-01-10 13:37:17 +00:00
/// <para>
/// (TargetType, (PropertyName, TargetPropertyName))
/// </para>
/// </summary>
private static readonly Dictionary<Type, ReflectionObjectInfo> _typePropertyReflectionInfos =
new();
2024-01-11 16:28:22 +00:00
public static void SetValue(object source, object target, ReflectionOptions options = null!)
2024-01-10 13:37:17 +00:00
{
options ??= new();
2024-01-11 16:28:22 +00:00
var sourceType = source.GetType();
var targetType = target.GetType();
2024-01-10 13:37:17 +00:00
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);
2024-01-11 16:28:22 +00:00
foreach (var property in targetType.GetProperties(_propertyBindingFlags))
2024-01-10 13:37:17 +00:00
{
2024-01-11 16:28:22 +00:00
// 尝试获取目标属性信息
targetInfo.PropertyInfos.TryGetValue(property.Name, out var targetReflectionInfo);
2024-01-13 13:56:21 +00:00
// 检测忽视
if (targetReflectionInfo?.IsIgnore is true)
continue;
2024-01-10 13:37:17 +00:00
// 获取源属性名
2024-01-11 16:28:22 +00:00
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);
2024-01-10 13:37:17 +00:00
continue;
2024-01-11 16:28:22 +00:00
}
2024-01-10 13:37:17 +00:00
// 获取源值
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)
{
2024-01-11 16:28:22 +00:00
var targetValue = targetAccessor[property.Name];
2024-01-10 13:37:17 +00:00
if (sourceValue.Equals(targetValue))
continue;
}
2024-01-11 16:28:22 +00:00
targetAccessor[property.Name] = sourceValue;
2024-01-10 13:37:17 +00:00
}
}
private static ReflectionObjectInfo GetReflectionObjectInfo(Type type)
{
var objectInfo = new ReflectionObjectInfo(type);
2024-01-11 16:28:22 +00:00
foreach (var property in type.GetProperties(_propertyBindingFlags))
2024-01-10 13:37:17 +00:00
{
2024-01-13 13:56:21 +00:00
// 获取是否被忽视
if (property.IsDefined(typeof(ReflectionPropertyIgnoreAttribute)))
{
objectInfo.PropertyInfos[property.Name] = new(property.Name) { IsIgnore = true };
continue;
}
2024-01-11 16:28:22 +00:00
if (
2024-01-13 13:56:21 +00:00
property.IsDefined(typeof(ReflectionPropertyIgnoreAttribute))
2024-01-11 16:28:22 +00:00
&& property.IsDefined(typeof(ReflectionPropertyConverterAttribute)) is false
)
continue;
var propertyInfo = new ReflectionPropertyInfo(property.Name);
// 获取属性信息
if (
property.GetCustomAttribute<ReflectionPropertyAttribute>()
is ReflectionPropertyAttribute propertyInfoAttribute
)
{
2024-01-13 13:56:21 +00:00
if (string.IsNullOrWhiteSpace(propertyInfoAttribute.TargetPropertyName) is false)
propertyInfo.TargetName = propertyInfoAttribute.TargetPropertyName;
2024-01-11 16:28:22 +00:00
propertyInfo.IsRequired = propertyInfoAttribute.IsRequired;
}
// 获取属性转换器
if (
property.GetCustomAttribute<ReflectionPropertyConverterAttribute>()
is ReflectionPropertyConverterAttribute propertyConverterAttribute
)
2024-01-10 13:37:17 +00:00
{
2024-01-12 14:17:50 +00:00
if (
_reflectionConverters.TryGetValue(
propertyConverterAttribute.ConverterType,
out var converter
)
is false
)
converter = _reflectionConverters[propertyConverterAttribute.ConverterType] =
(IReflectionConverter)
TypeAccessor
.Create(propertyConverterAttribute.ConverterType)
.CreateNew();
propertyInfo.Converter = converter;
2024-01-10 13:37:17 +00:00
}
2024-01-11 16:28:22 +00:00
objectInfo.PropertyInfos[property.Name] = propertyInfo;
2024-01-10 13:37:17 +00:00
}
return objectInfo;
}
}
/// <summary>
/// 反射对象信息
/// </summary>
public class ReflectionObjectInfo
{
public HashSet<string> PropertyNames { get; }
2024-01-11 16:28:22 +00:00
public Dictionary<string, ReflectionPropertyInfo> PropertyInfos { get; } = new();
2024-01-10 13:37:17 +00:00
public ReflectionObjectInfo(Type type)
{
2024-01-12 13:34:53 +00:00
PropertyNames = new(
type.GetProperties(BindingFlags.Instance | BindingFlags.Public).Select(p => p.Name)
);
2024-01-10 13:37:17 +00:00
}
}
2024-01-11 16:28:22 +00:00
public class ReflectionPropertyInfo
{
/// <summary>
/// 目标属性名称
/// </summary>
public string TargetName { get; set; }
/// <summary>
/// 是必要的
/// </summary>
2024-01-13 13:56:21 +00:00
[DefaultValue(false)]
public bool IsRequired { get; set; } = false;
/// <summary>
/// 是忽视的
/// </summary>
public bool IsIgnore { get; set; } = false;
2024-01-11 16:28:22 +00:00
/// <summary>
/// 反射值转换器
/// </summary>
public IReflectionConverter? Converter { get; set; } = null;
public ReflectionPropertyInfo(string propertyName)
{
TargetName = propertyName;
}
}
2024-01-10 13:37:17 +00:00
/// <summary>
/// 反射属性信息
/// </summary>
2024-01-11 16:28:22 +00:00
[AttributeUsage(AttributeTargets.Property)]
public class ReflectionPropertyAttribute : Attribute
2024-01-10 13:37:17 +00:00
{
/// <summary>
2024-01-11 16:28:22 +00:00
/// 属性名称
2024-01-10 13:37:17 +00:00
/// </summary>
2024-01-13 13:56:21 +00:00
public string TargetPropertyName { get; }
2024-01-10 13:37:17 +00:00
/// <summary>
2024-01-11 16:28:22 +00:00
/// 是必要的
2024-01-10 13:37:17 +00:00
/// </summary>
2024-01-11 16:28:22 +00:00
[DefaultValue(true)]
public bool IsRequired { get; } = true;
public ReflectionPropertyAttribute(bool isRequired = true)
{
IsRequired = isRequired;
}
2024-01-13 13:56:21 +00:00
public ReflectionPropertyAttribute(string targetPropertyName, bool isRequired = true)
2024-01-11 16:28:22 +00:00
{
2024-01-13 13:56:21 +00:00
TargetPropertyName = targetPropertyName;
2024-01-11 16:28:22 +00:00
IsRequired = isRequired;
}
}
2024-01-10 13:37:17 +00:00
2024-01-11 16:28:22 +00:00
/// <summary>
/// 反射属性转换器
/// </summary>
[AttributeUsage(AttributeTargets.Property)]
public class ReflectionPropertyConverterAttribute : Attribute
{
/// <summary>
/// 反射转换器
/// </summary>
2024-01-12 14:17:50 +00:00
public Type ConverterType { get; }
2024-01-10 13:37:17 +00:00
2024-01-11 16:28:22 +00:00
public ReflectionPropertyConverterAttribute(Type converterType)
2024-01-10 13:37:17 +00:00
{
2024-01-12 14:17:50 +00:00
ConverterType = converterType;
2024-01-10 13:37:17 +00:00
}
}
2024-01-13 13:56:21 +00:00
/// <summary>
/// 反射属性忽视
/// </summary>
[AttributeUsage(AttributeTargets.Property)]
public class ReflectionPropertyIgnoreAttribute : Attribute
{
public ReflectionPropertyIgnoreAttribute() { }
}
2024-01-10 13:37:17 +00:00
/// <summary>
/// 反射设置
/// </summary>
public class ReflectionOptions
{
/// <summary>
/// 检查值是否相等, 若相等则跳过赋值
/// </summary>
[DefaultValue(false)]
public bool CheckValueEquals { get; set; } = false;
2024-01-11 16:28:22 +00:00
/// <summary>
/// 未赋值的必要属性
/// </summary>
public List<string> UnassignedRequiredProperties { get; set; } = new();
2024-01-10 13:37:17 +00:00
}
/// <summary>
/// 反射转换器
/// </summary>
public interface IReflectionConverter
{
public object Convert(object sourceValue);
public object ConvertBack(object targetValue);
}
/// <summary>
/// 反射转换器
/// </summary>
/// <typeparam name="TSource">源值类型</typeparam>
/// <typeparam name="TTarget">目标值类型</typeparam>
public abstract class ReflectionConverterBase<TSource, TTarget> : 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);
}
}