/// <summary>
///创建一个映射表达式
/// </summary>
/// <typeparam name="TEntity"></typeparam>
/// <typeparam name="TDest"></typeparam>
/// <param name="dest"></param>
/// <returns></returns>
/// <exception cref="ArgumentNullException"></exception>
/// <exception cref="InvalidOperationException"></exception>
public static Expression<Func<SetPropertyCalls<TEntity>, SetPropertyCalls<TEntity>>>
CreateSetPropertyExpression<TEntity, TDest>(TDest dest)
{
if (dest == null)
{
throw new ArgumentNullException(nameof(dest));
}
ParameterExpression settersParameter = Expression.Parameter(typeof(SetPropertyCalls<TEntity>), "setters");
Type entityType = typeof(TEntity);
Type destType = typeof(TDest);
// 匿名类型的特殊处理:获取所有实例属性(包括只读属性)
PropertyInfo[] destProperties = destType.GetProperties(BindingFlags.Instance | BindingFlags.Public);
Expression currentExpression = settersParameter;
bool hasValidProperties = false;
foreach (PropertyInfo destProperty in destProperties)
{
// 跳过索引器属性(匿名类型不会包含)
if (destProperty.GetIndexParameters().Length > 0)
{
continue;
}
// 查找实体类中同名且可写的属性
PropertyInfo? entityProperty = entityType.GetProperty(
destProperty.Name,
BindingFlags.Instance | BindingFlags.Public | BindingFlags.IgnoreCase // 支持不区分大小写
);
if (entityProperty == null || !entityProperty.CanWrite)
{
continue;
}
// 获取匿名对象的属性值
object? destValue = destProperty.GetValue(dest);
// 处理类型转换(包括可空类型)
Type targetType = entityProperty.PropertyType;
try
{
destValue = ConvertValue(destValue, targetType);
}
catch (InvalidCastException ex)
{
throw new InvalidOperationException(
$"属性 {destProperty.Name} 类型转换失败: {ex.Message}", ex);
}
// 构建属性设置表达式
ParameterExpression entityParam = Expression.Parameter(entityType, "e");
MemberExpression propertyAccess = Expression.Property(entityParam, entityProperty);
LambdaExpression selector = Expression.Lambda(propertyAccess, entityParam);
// 创建常量表达式(支持null值)
ConstantExpression valueExpr = Expression.Constant(destValue, targetType);
// 获取泛型SetProperty方法
// 查找 SetProperty 方法
MethodInfo? setPropertyMethod = typeof(SetPropertyCalls<TEntity>).GetMethods().Where(d => d.Name == "SetProperty").ToArray()[1]?
.MakeGenericMethod(typeof(Func<,>).MakeGenericType(entityType, targetType), targetType) ?? throw new InvalidOperationException("setPropertyMethod 失败");
// 链式调用构建
currentExpression = Expression.Call(
currentExpression,
setPropertyMethod,
selector,
valueExpr
);
hasValidProperties = true;
}
return !hasValidProperties
? throw new InvalidOperationException("未找到可映射的属性")
: Expression.Lambda<Func<SetPropertyCalls<TEntity>, SetPropertyCalls<TEntity>>>(
currentExpression,
settersParameter
);
}
private static object? ConvertValue(object? value, Type targetType)
{
if (value == null)
{
return targetType.IsValueType && !IsNullableType(targetType)
? throw new InvalidCastException($"无法将null赋值给非可空类型 {targetType}")
: null;
}
Type sourceType = value.GetType();
Type underlyingTargetType = Nullable.GetUnderlyingType(targetType) ?? targetType;
// 类型直接匹配
if (underlyingTargetType.IsAssignableFrom(sourceType))
{
return value;
}
// 处理数值类型转换(如int到long)
return IsNumericType(sourceType) && IsNumericType(underlyingTargetType)
? Convert.ChangeType(value, underlyingTargetType)
: throw new InvalidCastException($"无法将类型 {sourceType} 转换为 {targetType}");
}
private static bool IsNullableType(Type type)
{
return type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>);
}
private static bool IsNumericType(Type type)
{
Type[] numericTypes = {
typeof(int), typeof(double), typeof(decimal),
typeof(long), typeof(short), typeof(float),
typeof(byte), typeof(uint), typeof(ulong),
typeof(ushort), typeof(sbyte)
};
return Array.Exists(numericTypes, t => t == type);
}