C#反射遍历枚举类型列表:无需硬编码获取元素的方法
问题
尝试从类中自动生成带默认值的UI,但无法获取枚举类型列表中的元素。已编写测试示例,希望在不硬编码所有枚举列表类型组合、不添加switch case语句的前提下,访问列表中的数据。
测试代码:
using System; using System.Reflection; using System.Collections.Generic; public class Program { public static void Main() { var options = new Options(); options.Foods = new List<Food>() {Food.Chips, Food.Pie}; options.Drinks = new List<Drink>() {Drink.Lemonade,Drink.Water}; foreach (PropertyInfo propertyInfo in options.GetType().GetProperties()) { Console.WriteLine(propertyInfo.Name); object vals = propertyInfo.GetValue(options); var type = propertyInfo.PropertyType.GetGenericArguments()[0]; Console.WriteLine(type); // Error is here, how can I loop through a enum list without // hard coding in each List<enum> type. foreach(var item in vals as IEnumerable<object>) { Console.WriteLine("--" + item.ToString()); } } } } public class Options { public List<Food> Foods {get;set;} public List<Drink> Drinks {get;set;} } public enum Food { Chips, Fish, Burger, Pie, Mash } public enum Drink { Cola, Lemonade, Water }
解决方案
问题根源是List<枚举类型>属于值类型泛型集合,无法直接转换为IEnumerable<object>(值类型的泛型集合不会自动装箱为object枚举)。以下两种方案可实现通用处理:
方法1:使用非泛型IEnumerable接口
直接将列表转换为非泛型的IEnumerable,遍历过程中元素会自动装箱为object:
foreach (PropertyInfo propertyInfo in options.GetType().GetProperties()) { Console.WriteLine(propertyInfo.Name); object vals = propertyInfo.GetValue(options); var type = propertyInfo.PropertyType.GetGenericArguments()[0]; Console.WriteLine(type); // 改用非泛型IEnumerable遍历 if (vals is IEnumerable enumerable) { foreach (var item in enumerable) { Console.WriteLine("--" + item.ToString()); } } }
方法2:反射调用泛型方法
如果需要对枚举值执行更多定制操作,可定义泛型方法并通过反射调用:
public static void Main() { var options = new Options(); options.Foods = new List<Food>() {Food.Chips, Food.Pie}; options.Drinks = new List<Drink>() {Drink.Lemonade,Drink.Water}; foreach (PropertyInfo propertyInfo in options.GetType().GetProperties()) { Console.WriteLine(propertyInfo.Name); object vals = propertyInfo.GetValue(options); var elementType = propertyInfo.PropertyType.GetGenericArguments()[0]; Console.WriteLine(elementType); // 反射调用泛型方法处理列表 typeof(Program).GetMethod("ProcessEnumList", BindingFlags.NonPublic | BindingFlags.Static) .MakeGenericMethod(elementType) .Invoke(null, new[] { vals }); } } private static void ProcessEnumList<T>(List<T> list) where T : Enum { foreach (var item in list) { Console.WriteLine("--" + item.ToString()); // 可在此添加枚举专属操作,比如获取枚举描述、数值等 } }
两种方案均无需硬编码具体枚举类型或添加switch case,完全通过反射与泛型实现通用化处理。
内容的提问来源于stack exchange,提问作者JW2022
相关产品推荐
相关产品推荐

