using System; using System.Collections.Generic; using System.Linq.Expressions; using System.Reflection; namespace StandardLibrary { public static class PropertyPathExtractor { /// /// 获得类型下的所有基本类型的访问路径 /// /// /// public static List GetLeafPropertyPaths(Type type) { if (type == null) return new List(); var visited = new HashSet(); var paths = new List(); Traverse(type, "", paths, visited); return paths; } private static void Traverse(Type type, string prefix, List paths, HashSet visited) { if (type == null || IsSimpleType(type)) return; if (!visited.Add(type)) // 防止循环引用 return; var properties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance); foreach (var prop in properties) { if (prop.GetIndexParameters().Length > 0) continue; // 跳过索引器 string currentPath = string.IsNullOrEmpty(prefix) ? prop.Name : $"{prefix}.{prop.Name}"; if (IsSimpleType(prop.PropertyType)) { // 只有叶子节点(基本类型)才加入路径 paths.Add(currentPath); } else { // 非简单类型:继续递归,但不记录 currentPath 本身 Traverse(prop.PropertyType, currentPath, paths, visited); } } visited.Remove(type); // 回溯(可选) } private static bool IsSimpleType(Type type) { if (type == null) return true; if (type.IsPrimitive || type == typeof(string) || type == typeof(decimal)) return true; if (type.IsEnum) return true; if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>)) return IsSimpleType(type.GetGenericArguments()[0]); return false; } } public static class PropertyPathHelper { //PropertyPathHelper.GetPath(()=>a.b.c),输出a.b.c public static string GetPath(Expression> expression) { return GetMemberPath(expression.Body); } private static string GetMemberPath(Expression expression) { switch (expression) { case MemberExpression memberExpr: if (memberExpr.Expression is ParameterExpression) return memberExpr.Member.Name; // 顶层变量(实际不会出现,因为是 Func) string parentPath = GetMemberPath(memberExpr.Expression); return parentPath + "." + memberExpr.Member.Name; case ConstantExpression constExpr: // 静态成员或 null 常量,无法构成路径 //throw new ArgumentException("表达式不能包含常量或静态成员"); return constExpr.Value.ToString(); default: throw new ArgumentException($"不支持的表达式类型: {expression.GetType().Name}"); } } } public static class PropertyFinder { /// /// 查找指定对象的(非静态)属性中,值为 T 类型(或其派生类)的所有实例。 /// 不递归,仅检查当前对象的属性。 /// public static List FindPropertiesOfType(object obj) where T : class { if (obj == null) return new List(); var result = new List(); var type = obj.GetType(); // 获取所有实例属性(包括私有属性,如不需要可调整 BindingFlags) var properties = type.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); foreach (var prop in properties) { if (!prop.CanRead) continue; // 跳过索引器(如 this[int i]) if (prop.GetIndexParameters().Length > 0) continue; try { var value = prop.GetValue(obj) as T; if (value != null) { result.Add(value); } } catch (Exception) { // 忽略无法读取的属性(如抛异常的 lazy 属性等) } } return result; } } public static class ObjectPropertySetter { /// /// Sets the value of a nested property on the specified target object, navigating through the property path. /// /// This method supports setting values on nested properties by navigating through the /// specified property path. If any intermediate property in the path is , an instance of /// the corresponding type will be created, provided the type has a parameterless constructor. The final /// property in the path will be assigned the specified value, which will be converted to the property's type if /// necessary. /// The object on which the property value will be set. Cannot be . /// The dot-separated path of the property to set. Each segment represents a property name in the hierarchy. /// The value to assign to the specified property. The value will be converted to the property's type if /// necessary. /// Thrown if a property in the path does not exist on the corresponding object type. /// Thrown if an intermediate property in the path is and cannot be instantiated due to /// the absence of a parameterless constructor. public static void SetPropertyValue(object target, string propertyPath, object value) { var parts = propertyPath.Split('.'); object current = target; for (int i = 0; i < parts.Length; i++) { var propName = parts[i]; var prop = current.GetType().GetProperty(propName, BindingFlags.Public | BindingFlags.Instance); if (prop == null) throw new ArgumentException($"Property '{propName}' not found on type {current.GetType()}."); if (i == parts.Length - 1) { // 最后一级:赋值 var convertedValue = ConvertValue(value, prop.PropertyType); prop.SetValue(current, convertedValue); } else { // 中间级:获取子对象,若为 null 则创建(仅支持无参构造) var subObject = prop.GetValue(current); if (subObject == null) { var subType = prop.PropertyType; if (subType.GetConstructor(Type.EmptyTypes) == null) throw new InvalidOperationException($"Cannot create instance of {subType} (no parameterless constructor)."); subObject = Activator.CreateInstance(subType); prop.SetValue(current, subObject); } current = subObject; } } } /// /// Converts the specified value to the specified target type. /// /// This method supports conversion between compatible types, including basic types and /// enums. If the target type is an enumeration, the method attempts to convert the value to the corresponding /// enum value. /// The value to convert. Can be null. /// The type to which the value should be converted. Must not be null. /// The converted value as an object of the specified target type, or null if is null. /// Thrown if the conversion cannot be performed, such as when the value is incompatible with the target type. private static object ConvertValue(object value, Type targetType) { if (value == null) { // 返回 targetType 的 default 值,而不是简单返回 null return GetDefaultValue(targetType); } var sourceType = value.GetType(); if (targetType.IsAssignableFrom(sourceType)) return value; // 尝试类型转换(支持基本类型) try { if (targetType.IsEnum) return Enum.ToObject(targetType, value); return Convert.ChangeType(value, targetType); } catch (Exception ex) { throw new InvalidOperationException($"Cannot convert {value} ({sourceType}) to {targetType}", ex); } } public static object GetDefaultValue(Type type) { if (type == null) throw new ArgumentNullException(nameof(type)); // 引用类型(包括 string)或可空值类型(如 int?)的 default 是 null if (!type.IsValueType) return null; // 值类型:使用 Activator.CreateInstance 返回其零初始化值 return Activator.CreateInstance(type); } } }