C#如何动态指定对象字段,复用CSV写入函数?
解决动态访问Player属性写入CSV的问题
你遇到的核心问题是C#作为静态类型语言,无法直接通过字符串变量访问对象属性(playerarray[i].arg这种写法会被编译器识别为访问Player类的arg属性,而非你传入的字符串对应的目标属性)。下面提供两种实用解决思路:
方法1:使用反射实现动态属性访问
反射可在运行时获取类型信息,动态读取对象属性值。修改WriteSpecificPlayerInfo方法如下:
public static void WritePlayerInfo(Player[] playerArray, StreamWriter writer) { WriteSpecificPlayerInfo(playerArray, writer, "Name"); WriteSpecificPlayerInfo(playerArray, writer, "Class"); // 其他字段... } public static void WriteSpecificPlayerInfo(Player[] playerArray, StreamWriter writer, string propertyName) { // 获取Player类的指定属性 var property = typeof(Player).GetProperty(propertyName); if (property == null) { throw new ArgumentException($"Player类不存在名为{propertyName}的属性"); } for (int i = 0; i < playerArray.Length; i++) { // 动态获取属性值,空值转为空字符串 var value = property.GetValue(playerArray[i])?.ToString() ?? string.Empty; if (i == playerArray.Length - 1) { writer.WriteLine(value); } else { writer.Write($"{value};"); } } }
注意:反射存在一定性能开销,处理大量数据时建议优先用方法2。
方法2:使用委托(Func<Player, object>)实现类型安全访问
通过委托传递属性访问逻辑,编译时即可验证属性存在性,性能比反射更优:
public static void WritePlayerInfo(Player[] playerArray, StreamWriter writer) { WriteSpecificPlayerInfo(playerArray, writer, p => p.Name); WriteSpecificPlayerInfo(playerArray, writer, p => p.Class); // 其他字段... } public static void WriteSpecificPlayerInfo(Player[] playerArray, StreamWriter writer, Func<Player, object> propertyAccessor) { // 用String.Join简化分隔符处理,避免循环内的条件判断 var values = string.Join(";", playerArray.Select(p => propertyAccessor(p)?.ToString() ?? string.Empty)); writer.WriteLine(values); }
这种写法更简洁,还能提前规避属性不存在的运行时错误。
额外优化:生成标准CSV格式(可选)
如果需要生成每行对应一个Player、每列对应一个字段的标准CSV,可封装为一次性写入所有字段:
public static void WritePlayersToCsv(Player[] playerArray, StreamWriter writer, params Func<Player, object>[] propertyAccessors) { // 写入表头(可选) var headers = propertyAccessors.Select(accessor => accessor.Method.Name.Replace("get_", "")); // 从委托方法名提取属性名 writer.WriteLine(string.Join(";", headers)); // 写入每行数据 foreach (var player in playerArray) { var values = string.Join(";", propertyAccessors.Select(accessor => accessor(player)?.ToString() ?? string.Empty)); writer.WriteLine(values); } } // 调用示例 WritePlayersToCsv(playerArray, writer, p => p.Name, p => p.Class);
内容的提问来源于stack exchange,提问作者Lolipop
相关产品推荐
相关产品推荐

