如何在C#中动态处理TheCocktailDB饮品的可变配料与测量字段
动态处理TheCocktailDB饮品配料与测量值的解决方案
问题背景
我正在开发一个从TheCocktailDB API获取饮品详情的项目,每种饮品最多包含15种配料及对应测量值,但实际配料数量因饮品而异。我希望以表格格式动态展示这些数据,目前遇到两个问题:
- 无法动态处理每种饮品数量可变的配料与测量值
- 无法在不硬编码列名的情况下将数据转换为键值对格式(如
Ingredient1 -> Vodka)
现有代码
Drink类定义
public class Drink { public string? strDrink { get; set; } public string? strIngredient1 { get; set; } public string? strIngredient2 { get; set; } // up to strIngredient15 public string? strMeasure1 { get; set; } public string? strMeasure2 { get; set; } // up to strMeasure15 }
当前遍历代码
foreach (var drink in _drinkDetails.drinks) { Console.WriteLine($"Drink Name: {drink.strDrink}"); // How do I dynamically iterate through the ingredients and measures here? }
解决方案
方法1:使用反射动态遍历属性
通过反射自动识别并筛选出所有配料和测量值属性,按序号配对后展示,无需硬编码属性名:
foreach (var drink in _drinkDetails.drinks) { Console.WriteLine($"饮品名称: {drink.strDrink}"); Console.WriteLine("| 配料 | 测量值 |"); Console.WriteLine("|------|--------|"); // 获取所有非空的配料属性并按序号排序 var ingredientProps = typeof(Drink).GetProperties() .Where(p => p.Name.StartsWith("strIngredient") && p.GetValue(drink) != null) .OrderBy(p => p.Name) .ToList(); // 获取所有非空的测量值属性并按序号排序 var measureProps = typeof(Drink).GetProperties() .Where(p => p.Name.StartsWith("strMeasure") && p.GetValue(drink) != null) .OrderBy(p => p.Name) .ToList(); // 按序号配对展示,处理数量不一致的情况 int maxPairs = Math.Max(ingredientProps.Count, measureProps.Count); for (int i = 0; i < maxPairs; i++) { string ingredient = i < ingredientProps.Count ? ingredientProps[i].GetValue(drink)?.ToString() ?? "-" : "-"; string measure = i < measureProps.Count ? measureProps[i].GetValue(drink)?.ToString() ?? "-" : "-"; Console.WriteLine($"| {ingredient} | {measure} |"); } Console.WriteLine(); }
方法2:重构Drink类,使用集合存储配料
如果允许修改Drink类,将硬编码的15组属性替换为集合,会让数据处理更简洁。可以在反序列化后转换数据:
// 重构后的Drink类 public class Drink { public string? strDrink { get; set; } public List<(string Ingredient, string Measure)> Ingredients { get; set; } = new(); } // 数据转换与展示代码 foreach (var rawDrink in _drinkDetails.drinks) { var drink = new Drink { strDrink = rawDrink.strDrink }; // 遍历1到15的属性,提取非空配料 for (int i = 1; i <= 15; i++) { var ingredientProp = rawDrink.GetType().GetProperty($"strIngredient{i}"); var measureProp = rawDrink.GetType().GetProperty($"strMeasure{i}"); if (ingredientProp == null || measureProp == null) continue; string? ingredient = ingredientProp.GetValue(rawDrink)?.ToString(); if (!string.IsNullOrEmpty(ingredient)) { string measure = measureProp.GetValue(rawDrink)?.ToString() ?? "-"; drink.Ingredients.Add((ingredient, measure)); } } // 输出表格 Console.WriteLine($"饮品名称: {drink.strDrink}"); Console.WriteLine("| 配料 | 测量值 |"); Console.WriteLine("|------|--------|"); foreach (var item in drink.Ingredients) { Console.WriteLine($"| {item.Ingredient} | {item.Measure} |"); } Console.WriteLine(); }
方法3:手动遍历属性(无反射)
如果不想使用反射,也可以手动编写循环遍历1到15的属性,代码稍显重复但可读性高:
foreach (var drink in _drinkDetails.drinks) { Console.WriteLine($"饮品名称: {drink.strDrink}"); Console.WriteLine("| 配料 | 测量值 |"); Console.WriteLine("|------|--------|"); for (int i = 1; i <= 15; i++) { string? ingredient = i switch { 1 => drink.strIngredient1, 2 => drink.strIngredient2, 3 => drink.strIngredient3, 4 => drink.strIngredient4, 5 => drink.strIngredient5, 6 => drink.strIngredient6, 7 => drink.strIngredient7, 8 => drink.strIngredient8, 9 => drink.strIngredient9, 10 => drink.strIngredient10, 11 => drink.strIngredient11, 12 => drink.strIngredient12, 13 => drink.strIngredient13, 14 => drink.strIngredient14, 15 => drink.strIngredient15, _ => null }; string? measure = i switch { 1 => drink.strMeasure1, 2 => drink.strMeasure2, 3 => drink.strMeasure3, 4 => drink.strMeasure4, 5 => drink.strMeasure5, 6 => drink.strMeasure6, 7 => drink.strMeasure7, 8 => drink.strMeasure8, 9 => drink.strMeasure9, 10 => drink.strMeasure10, 11 => drink.strMeasure11, 12 => drink.strMeasure12, 13 => drink.strMeasure13, 14 => drink.strMeasure14, 15 => drink.strMeasure15, _ => null }; if (!string.IsNullOrEmpty(ingredient)) { Console.WriteLine($"| {ingredient} | {measure ?? "-"} |"); } } Console.WriteLine(); }
内容的提问来源于stack exchange,提问作者AhmadJer99
相关产品推荐
相关产品推荐

