.NET 6中如何针对两个含公共字段的类正确使用泛型实例化对象
解决泛型方法适配多类的问题
你的问题核心在于当前泛型方法的约束where T : ABC, new()把类型死死限制在了ABC及其子类上,自然无法处理BCD。要适配这两个类,我们需要先打破这个约束,同时安全地处理它们的公共字段和各自的独有字段,下面是两种可行的方案:
方案一:提取公共接口/基类(推荐,类型安全)
这是最规范的做法,通过抽象公共字段来复用逻辑,同时保留对独有字段的处理能力:
步骤1:定义公共抽象层
先把ABC和BCD的公共字段抽成一个接口或者基类,这里用接口举例:
public interface IReportBase { int pageId { get; set; } string paperType { get; set; } int Volume { get; set; } }
步骤2:让目标类实现这个接口
修改ABC和BCD,让它们都实现IReportBase:
public class ABC : IReportBase { // 公共字段(来自接口) public int pageId { get; set; } public string paperType { get; set; } public int Volume { get; set; } // ABC独有字段 public string printType { get; set; } } public class BCD : IReportBase { // 公共字段(来自接口) public int pageId { get; set; } public string paperType { get; set; } public int Volume { get; set; } // BCD独有字段 public string paperColor { get; set; } public int Weight { get; set; } }
步骤3:修改泛型方法
更新FillReport的约束,同时通过类型判断处理各自的独有字段:
public T FillReport<T>(DTO? dto) where T : IReportBase, new() { if (dto == null) return default(T); T report = new T(); // 公共字段统一赋值,编译时安全检查 report.pageId = dto.pageId; report.paperType = dto.paperType; report.Volume = dto.Volume; // 处理ABC的独有字段 if (report is ABC abcReport) { abcReport.printType = dto.printType; // 假设DTO包含该字段 } // 处理BCD的独有字段 else if (report is BCD bcdReport) { bcdReport.paperColor = dto.paperColor; // 假设DTO包含该字段 bcdReport.Weight = dto.Weight; } return report; }
这样修改后,你原来的调用代码完全不需要改动,FillReport<ABC>和FillReport<BCD>都能正常工作,而且所有字段赋值都有编译时检查,不会出现拼写错误。
方案二:使用反射(适合无法修改现有类的场景)
如果因为某些原因不能修改ABC和BCD的结构,可以用反射来绕过类型约束,但这种方式没有编译时检查,性能也稍差:
public T FillReport<T>(DTO? dto) where T : new() { if (dto == null) return default(T); T report = new T(); Type reportType = typeof(T); // 公共字段反射赋值 AssignField(report, reportType, "pageId", dto.pageId); AssignField(report, reportType, "paperType", dto.paperType); AssignField(report, reportType, "Volume", dto.Volume); // 处理ABC独有字段 if (reportType == typeof(ABC)) { AssignField(report, reportType, "printType", dto.printType); } // 处理BCD独有字段 else if (reportType == typeof(BCD)) { AssignField(report, reportType, "paperColor", dto.paperColor); AssignField(report, reportType, "Weight", dto.Weight); } return report; } // 辅助方法:反射给字段赋值 private void AssignField<TTarget>(object obj, Type type, string fieldName, TTarget value) { var field = type.GetField(fieldName); field?.SetValue(obj, value); }
总结
优先选择方案一,它兼顾了代码的可读性、类型安全性和扩展性;只有当无法修改现有类结构时,再考虑方案二。
内容的提问来源于stack exchange,提问作者Peter
相关产品推荐
相关产品推荐

