C#中如何通过反射获取嵌套元组元素名称并关联元素与名称
在C#中通过反射关联嵌套元组元素与TupleElementNamesAttribute的名称
对于嵌套值元组的场景,TupleElementNamesAttribute.TransformNames返回的是扁平化的名称数组,其顺序遵循固定规则:先按顺序列出当前元组的所有顶层元素名称,再依次递归遍历每个顶层元素(若为元组类型)的内部元素名称。只要按照这个顺序递归遍历元组的类型结构,就能将每个嵌套元素和对应的名称关联起来。
规则验证
以你给出的方法为例:
public static void M(((int n1, uint n2) o1, ((int p1, (int w1, uint w2) p2, uint p3) q1, ((int x1, uint x2) r1, byte r2) q2) o2) k) {}
TransformNames数组的顺序为:"o1", "o2", "n1", "n2", "q1", "q2", "p1", "p2", "p3", "w1", "w2", "r1", "r2", "x1", "x2",对应遍历顺序:
- 最外层元组的顶层元素:
o1、o2 - 递归处理
o1的内部元素:n1、n2 - 递归处理
o2的内部元素:q1、q2 - 递归处理
q1的内部元素:p1、p2、p3 - 递归处理
p2的内部元素:w1、w2 - 递归处理
q2的内部元素:r1、r2 - 递归处理
r1的内部元素:x1、x2
实现代码
以下是递归遍历元组类型并关联名称的工具类:
using System; using System.Collections.Generic; using System.Reflection; using System.Runtime.CompilerServices; public class TupleNameMapper { // 生成嵌套元组元素的路径-名称映射 public static Dictionary<string, string> MapNestedTupleNames(Type tupleType, string[] transformNames) { var nameMap = new Dictionary<string, string>(); var nameEnumerator = ((IEnumerable<string>)transformNames).GetEnumerator(); RecurseTuple(tupleType, string.Empty, nameEnumerator, nameMap); return nameMap; } private static void RecurseTuple(Type type, string parentPath, IEnumerator<string> nameEnumerator, Dictionary<string, string> nameMap) { if (!IsValueTuple(type)) return; // 获取当前元组的所有元素类型 var elementTypes = type.GetGenericArguments(); foreach (var elementType in elementTypes) { nameEnumerator.MoveNext(); var elementName = nameEnumerator.Current; // 构建元素的完整路径(如 o1.n1) var fullPath = string.IsNullOrEmpty(parentPath) ? elementName : $"{parentPath}.{elementName}"; nameMap[fullPath] = elementName; // 递归处理子元组 if (IsValueTuple(elementType)) { RecurseTuple(elementType, fullPath, nameEnumerator, nameMap); } } } // 判断类型是否为值元组 private static bool IsValueTuple(Type type) { return type.IsGenericType && type.GetGenericTypeDefinition().Namespace == "System" && type.GetGenericTypeDefinition().Name.StartsWith("ValueTuple`", StringComparison.Ordinal); } }
使用示例
public class Program { public static void M(((int n1, uint n2) o1, ((int p1, (int w1, uint w2) p2, uint p3) q1, ((int x1, uint x2) r1, byte r2) q2) o2) k) {} public static void Main() { // 获取方法参数信息 var methodInfo = typeof(Program).GetMethod(nameof(M)); var parameterInfo = methodInfo.GetParameters()[0]; var tupleAttr = parameterInfo.GetCustomAttribute<TupleElementNamesAttribute>(); var transformNames = tupleAttr.TransformNames; // 生成映射 var nameMap = TupleNameMapper.MapNestedTupleNames(parameterInfo.ParameterType, transformNames); // 输出结果 foreach (var kvp in nameMap) { Console.WriteLine($"{kvp.Key}: {kvp.Value}"); } } }
输出结果
运行后会输出每个嵌套元素的完整路径和对应的名称:
o1: o1 o1.n1: n1 o1.n2: n2 o2: o2 o2.q1: q1 o2.q1.p1: p1 o2.q1.p2: p2 o2.q1.p2.w1: w1 o2.q1.p2.w2: w2 o2.q1.p3: p3 o2.q2: q2 o2.q2.r1: r1 o2.q2.r1.x1: x1 o2.q2.r1.x2: x2 o2.q2.r2: r2
内容的提问来源于stack exchange,提问作者viruseg
相关产品推荐
相关产品推荐

