如何用C#扩展方法将扁平列表按Code分组转换为层级数据
Got it, let's tackle this problem of transforming your flat ItemAssignmentFlatList data into the hierarchical ItemInfo structure (with nested TaxPlan lists) using clean, optimized C# extension methods. First, let's recap the requirements and fix up the existing code.
First, Let's Confirm the Class Definitions
Just to make sure we're on the same page, here are the source and target classes you provided:
Source flat data class:
public class ItemAssignmentFlatList { public int Code { get; set; } public string Type { get; set; } public string Description { get; set; } public int ItemCode{ get; set; } public DateTime EffectiveDate{ get; set; } public string Area{ get; set; } public string TaxCode{ get; set; } public string LocationId { get; set; } }
Target hierarchical classes:
public class ItemInfo { public int Code { get; set; } public string Type { get; set; } public string Description { get; set; } public List<TaxPlan> TaxPlan { get; set; } } public class TaxPlan { public int ItemCode{ get; set; } public DateTime EffectiveDate{ get; set; } public string Area{ get; set; } public string TaxCode{ get; set; } public string LocationId { get; set; } }
Issues with the Existing Code
Your current code works, but has a few areas for improvement:
- Unnecessary calls to
FirstOrDefault(): Since you're grouping byCodeandType, every item in the group shares those values—you can use the group's key directly instead. - Incomplete property mapping: Your
TaxPlanprojection only mapsItemCodeand uses an incorrectTaxArea(the source class hasAreainstead). - Lack of reusability: The logic isn't encapsulated, making it hard to reuse across your codebase.
Optimized Extension Method Solution
Let's wrap this logic in a clean extension method that fixes these issues and makes your code more maintainable:
public static class ItemAssignmentExtensions { public static List<ItemInfo> ToHierarchicalItemInfo(this IEnumerable<ItemAssignmentFlatList> flatItems) { // Guard clause to handle null input (optional but good practice) if (flatItems == null) throw new ArgumentNullException(nameof(flatItems)); return flatItems // Group by Code + Type + Description (assuming same Code/Type have same Description) .GroupBy(item => new { item.Code, item.Type, item.Description }) // Project each group to an ItemInfo .Select(group => new ItemInfo { Code = group.Key.Code, Type = group.Key.Type, Description = group.Key.Description, // Project all items in the group to TaxPlan objects TaxPlan = group.Select(flatItem => new TaxPlan { ItemCode = flatItem.ItemCode, EffectiveDate = flatItem.EffectiveDate, Area = flatItem.Area, TaxCode = flatItem.TaxCode, LocationId = flatItem.LocationId }).ToList() }) .ToList(); } }
Key Improvements Explained
- Extension Method Encapsulation: Now you can call this method directly on any
IEnumerable<ItemAssignmentFlatList>—no need to repeat the grouping logic everywhere. - Use Group Key Instead of FirstOrDefault: The group's key contains the shared
Code,Type, andDescription(assuming your business logic guarantees sameCode/Typepairs have the sameDescription). This is more efficient and avoids unnecessary enumeration. - Complete Property Mapping: All
TaxPlanproperties are correctly mapped from the source data. - Null Safety: Added a guard clause to handle null input gracefully.
If Description Might Vary for Same Code/Type
If your data allows for different Description values under the same Code and Type, adjust the grouping to only use Code and Type, then pick the first Description from the group:
public static List<ItemInfo> ToHierarchicalItemInfo(this IEnumerable<ItemAssignmentFlatList> flatItems) { if (flatItems == null) throw new ArgumentNullException(nameof(flatItems)); return flatItems .GroupBy(item => new { item.Code, item.Type }) .Select(group => new ItemInfo { Code = group.Key.Code, Type = group.Key.Type, Description = group.First().Description, // Pick first description in the group TaxPlan = group.Select(flatItem => new TaxPlan { ItemCode = flatItem.ItemCode, EffectiveDate = flatItem.EffectiveDate, Area = flatItem.Area, TaxCode = flatItem.TaxCode, LocationId = flatItem.LocationId }).ToList() }) .ToList(); }
How to Use It
Using the extension method is straightforward:
// Assume 'results' is your IEnumerable<ItemAssignmentFlatList> var hierarchicalResult = results.ToHierarchicalItemInfo();
内容的提问来源于stack exchange,提问作者VR1256

