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

如何无需Switch/Case实现多类型DomainObject批量写入数据库?

替代Switch/Case的几种实用方案

针对你现在用Switch/Case处理多类型实体批量写入的场景,这里有几个更灵活、易维护的替代方案,适配不同的场景需求:

方案1:类型-处理逻辑字典映射

提前把实体类型和对应的创建逻辑绑定到字典里,遍历的时候直接根据类型取逻辑执行,不用写硬编码的Switch/Case。后续新增实体,只需要往字典里加一条条目就行。

代码示例:

先在Program类里初始化这个映射字典:

public class Program
{
    public static List<DomainObject> allItems;
    public static DbContextFactory dbContextFactory = new DbContextFactory();
    
    // 提前构建类型到创建委托的映射
    private static readonly Dictionary<Type, Func<DomainObject, Task>> _entityCreators;

    static Program()
    {
        _entityCreators = new Dictionary<Type, Func<DomainObject, Task>>
        {
            { typeof(Resistor), async item => await new GenericDataService<Resistor>(dbContextFactory).Create((Resistor)item) },
            { typeof(Capacitor), async item => await new GenericDataService<Capacitor>(dbContextFactory).Create((Capacitor)item) },
            { typeof(Transistor), async item => await new GenericDataService<Transistor>(dbContextFactory).Create((Transistor)item) }
        };
    }

    static void Main(string[] args)
    {
       allItems = new List<DomainObject>
       {
         new Resistor(),
         new Capacitor(),
         new Transistor(),
       };
    }
}

然后修改批量写入的方法(注意改成异步,之前的代码没等待Create完成,会有异步问题):

public static async Task AddItemsToDatabase()
{
    foreach(var item in allItems)
    {
        if (_entityCreators.TryGetValue(item.GetType(), out var createLogic))
        {
            await createLogic(item);
        }
        else
        {
            // 处理未知类型,比如抛异常或者打日志
            throw new NotSupportedException($"不支持的实体类型:{item.GetType().Name}");
        }
    }
}

方案2:反射动态调用泛型服务

用反射自动创建对应类型的GenericDataService实例并调用Create方法,不用手动维护每个类型的映射,适合实体类型多、经常新增的场景。

代码示例:

public static async Task AddItemsToDatabase()
{
    foreach(var item in allItems)
    {
        Type entityType = item.GetType();
        // 动态构建GenericDataService<T>的类型
        Type serviceType = typeof(GenericDataService<>).MakeGenericType(entityType);
        // 创建服务实例
        object dataService = Activator.CreateInstance(serviceType, dbContextFactory);
        
        // 获取Create方法并调用
        MethodInfo createMethod = serviceType.GetMethod(nameof(GenericDataService<DomainObject>.Create));
        await (Task)createMethod.Invoke(dataService, new[] { item });
    }
}

如果担心反射性能,可以缓存一下serviceType和createMethod,比如用一个静态字典存类型对应的方法,避免每次循环都反射。

方案3:访问者模式(需修改实体类)

如果允许修改DomainObject及其子类,用访问者模式可以完全消除Switch/Case,符合开闭原则,新增实体时只需要扩展代码,不用修改原有批量逻辑。

第一步,定义访问者接口:

public interface IEntityVisitor
{
    Task Visit(Resistor resistor);
    Task Visit(Capacitor capacitor);
    Task Visit(Transistor transistor);
}

第二步,给DomainObject抽象类加Accept方法:

public abstract class DomainObject
{
    public ItemType ItemType { get; set; }
    public abstract Task Accept(IEntityVisitor visitor);
}

第三步,每个实体类实现Accept:

public class Resistor : DomainObject
{
    public override async Task Accept(IEntityVisitor visitor)
    {
        await visitor.Visit(this);
    }
}

public class Capacitor : DomainObject
{
    public override async Task Accept(IEntityVisitor visitor)
    {
        await visitor.Visit(this);
    }
}

public class Transistor : DomainObject
{
    public override async Task Accept(IEntityVisitor visitor)
    {
        await visitor.Visit(this);
    }
}

第四步,实现创建逻辑的访问者:

public class EntityCreatorVisitor : IEntityVisitor
{
    private readonly DbContextFactory _dbContextFactory;

    public EntityCreatorVisitor(DbContextFactory dbContextFactory)
    {
        _dbContextFactory = dbContextFactory;
    }

    public async Task Visit(Resistor resistor)
    {
        await new GenericDataService<Resistor>(_dbContextFactory).Create(resistor);
    }

    public async Task Visit(Capacitor capacitor)
    {
        await new GenericDataService<Capacitor>(_dbContextFactory).Create(capacitor);
    }

    public async Task Visit(Transistor transistor)
    {
        await new GenericDataService<Transistor>(_dbContextFactory).Create(transistor);
    }
}

最后修改批量写入方法:

public static async Task AddItemsToDatabase()
{
    var creatorVisitor = new EntityCreatorVisitor(dbContextFactory);
    foreach(var item in allItems)
    {
        await item.Accept(creatorVisitor);
    }
}

内容的提问来源于stack exchange,提问作者Iliya Belan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 15:15:13