You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 15:15:17