如何获取C#中dynamic动态对象指定索引字段的数据类型
可行实现方案
C#的普通动态对象、匿名类型对象默认不支持直接通过整数索引访问序号对应的属性,你可以通过反射、运行时类型转换的方式实现需求,对应不同动态对象类型的实现如下:
针对匿名类型动态对象(即你给出的示例场景)
你示例中用new { ... }声明的是匿名类型对象,这类对象的属性顺序和声明顺序严格一致,可以先把动态对象转为object拿到运行时类型,再通过反射获取属性列表,按索引读取对应字段的类型即可,可直接运行的代码如下:
dynamic dynamicObject = new { Name = "Bla", Age = 2, Surname = "Bla Bla" }; int index = 2; // 反射获取对象所有公开实例属性 Type runtimeType = ((object)dynamicObject).GetType(); PropertyInfo[] properties = runtimeType.GetProperties(); // 先做索引合法性校验,避免越界异常 if (index >= 0 && index < properties.Length) { // 方案1:直接读取属性声明的类型,不需要获取属性值,性能更好 Type fieldType = properties[index].PropertyType; // 方案2:读取属性实际值后获取运行时类型,适合属性值可能是声明类型派生类的场景 // object fieldValue = properties[index].GetValue(dynamicObject); // Type fieldType = fieldValue?.GetType() ?? typeof(object); // 上述示例中index=2对应Surname字段,返回结果为System.String,和预期一致 Console.WriteLine(fieldType.FullName); }
针对包含Fields索引属性的动态对象(即你伪代码描述的场景)
如果你的动态对象本身就有名为Fields、支持整数索引访问的成员(比如数组、List集合、自定义索引器),直接读取索引位置的值后调用GetType()方法即可:
// 示例:带Fields集合属性的动态对象 dynamic dynamicObject = new { Fields = new object[] { 123, "testStr", 3.14 } }; int index = 1; object targetValue = dynamicObject.Fields[index]; Type fieldType = targetValue?.GetType() ?? typeof(object); // 此处index=1对应字符串值,返回System.String
针对ExpandoObject类型的动态对象
如果你的动态对象是ExpandoObject实例,可以直接将其转为字典类型,通过LINQ按索引取对应值拿类型:
dynamic dynamicObject = new ExpandoObject(); dynamicObject.Name = "Bla"; dynamicObject.Age = 2; dynamicObject.Surname = "Bla Bla"; int index = 2; var propDict = (IDictionary<string, object>)dynamicObject; if (index >=0 && index < propDict.Count) { object targetValue = propDict.ElementAt(index).Value; Type fieldType = targetValue?.GetType() ?? typeof(object); // 同样返回System.String }
注意事项:
- 所有索引访问前必须做越界校验,取值后做空值判断,避免触发运行时异常
- 如果是自行继承
DynamicObject实现的自定义动态类型,需要你自己在类内实现按索引返回成员的逻辑,反射无法识别动态添加的自定义成员- 匿名类型、ExpandoObject的成员顺序和你添加/声明的顺序完全一致,可以放心按索引读取
内容的提问来源于stack exchange,提问作者Farid Murshudov
相关产品推荐
相关产品推荐

