C#中属性不同的类如何根据supplierType实现互换使用
实现方案
你的思路方向是正确的,核心问题是没有为Person和Organization定义统一的抽象契约,导致两类不同结构的对象无法被统一持有和调度,按以下步骤实现即可:
第一步:定义公共策略接口
把两类供应商共有的属性、行为抽象到ISupplier接口,作为所有供应商类型的统一约束:
public interface ISupplier { // 公共属性:对外展示的供应商名称 string DisplayName { get; } // 公共行为:将供应商信息持久化到数据库,不同类型自行实现对应逻辑 void SaveToDatabase(); }
第二步:让现有实体类实现接口
修改Person和Organization类,实现ISupplier接口,各自封装自身的属性逻辑:
public class Person : ISupplier { public string FirstName { get; set; } public string LastName { get; set; } public string? MiddleName { get; set; } public string DisplayName { get { return string.IsNullOrWhiteSpace(MiddleName) ? $"{FirstName} {LastName}" : $"{FirstName} {MiddleName} {LastName}"; } } public void SaveToDatabase() { // 此处编写个人供应商专属的入库逻辑,直接使用类下的FirstName/LastName/MiddleName字段 } } public class Organization : ISupplier { public string OrganizationName { get; set; } public string DisplayName => OrganizationName; public void SaveToDatabase() { // 此处编写组织供应商专属的入库逻辑,直接使用类下的OrganizationName字段 } }
第三步:优化Supplier类,封装实例创建逻辑
不要在主流程里写分支判断创建实例,把对应逻辑封装到Supplier的工厂方法中,降低耦合:
public class Supplier { public int SupplierType { get; set; } public ISupplier SupplierInfo { get; set; } public List<Product> Products { get; set; } = new(); /// <summary> /// 根据文件行解析出的字段,创建对应类型的供应商实例 /// </summary> public static ISupplier CreateSupplierInstance(int supplierType, string firstName, string lastName, string? middleName) { return supplierType switch { 1 => new Person { FirstName = firstName, LastName = lastName, MiddleName = middleName }, 2 => new Organization { // 按照文件规则,组织供应商名称存储在LastName字段 OrganizationName = lastName }, _ => throw new ArgumentOutOfRangeException(nameof(supplierType), $"无效的供应商类型值:{supplierType}") }; } }
第四步:主流程调用
主流程只需要和ISupplier接口交互,不需要关心底层是个人还是组织供应商:
void Main() { // 逐行读取管道分隔的供应商文本文件 foreach (var rawLine in File.ReadLines("供应商文件路径.txt")) { var fields = rawLine.Split('|'); // 按实际文件的字段顺序解析值,以下索引仅做示例 int supplierType = int.Parse(fields[0]); string firstName = fields[1]; string lastName = fields[2]; string? middleName = string.IsNullOrWhiteSpace(fields[3]) ? null : fields[3]; Supplier purchaseSupplier = new Supplier { SupplierType = supplierType, SupplierInfo = Supplier.CreateSupplierInstance(supplierType, firstName, lastName, middleName) }; // 后续业务逻辑无需判断类型,直接调用接口公共方法即可 Console.WriteLine($"正在导入供应商:{purchaseSupplier.SupplierInfo.DisplayName}"); purchaseSupplier.SupplierInfo.SaveToDatabase(); // 处理关联产品列表的逻辑... } }
设计说明
- 该实现完全符合策略模式的设计要求:
ISupplier是抽象策略,Person/Organization是具体策略实现,Supplier作为上下文持有策略实例,运行时根据supplierType自动切换具体实现 - 两类供应商的属性差异完全被封装在各自的类内部,上层业务逻辑不需要感知差异,解决了你提到的属性不统一问题
- 如果后续需要新增供应商类型,只需要新增一个实现
ISupplier接口的类,在工厂方法中增加对应分支即可,不需要修改现有上层逻辑,符合开闭原则 - 如果特定场景需要访问某类供应商独有的属性,可以通过C#模式匹配做类型判断后访问:
if (purchaseSupplier.SupplierInfo is Person personInfo) { // 此处可安全访问Person类独有的FirstName/MiddleName等属性 Console.WriteLine($"个人供应商中间名:{personInfo.MiddleName}"); }
内容的提问来源于stack exchange,提问作者Learn Tech
相关产品推荐
相关产品推荐

