如何避免嵌套开关结构?

How to avoid nested switch constructions?

比如我有两个classes

 public class A
 {
     public Guid Id { get; set;}
     public string Type { get; set; }
     public string State { get; set; }
     public string SomeProperty { get; set; }
 }

 public class B 
 {
     public Guid Id { get; set; }
     public string Type { get; set; }
     public string State { get; set; }
     public string AnotherProperty { get; set; }
 }

每个 class 都有自己的存储库

 public class RepA
 {
     public void Add(A entity)
     {
         // some specific logic here
     }

     public void Delete(A entity)
     {
         // some specific logic here
     }
 }

 public class RepB
 {
     public void Add(B entity)
     {
         // some specific logic here
     }

     public void Delete(B entity)
     {
         // some specific logic here
     }
 }

我需要实现一种方法来保存具有动态类型的实体列表。我想避免使用嵌套的 "switch" 结构(如下所列),因为我有超过 2 种类型和超过 2 种状态,代码看起来很乱。

 private readonly RepA _repA = new RepA();
 private readonly RepB _repB = new RepB();

 public void SaveChanges(List<dynamic> entities)
 {
      foreach (var entity in entities)
      {
           switch (entity.Type)
           {
                case "A": 
                     var a = entity as A;
                     switch (entity.State)
                     {
                          case "Added":
                               _repA.Add(a);
                               break;
                          case "Deleted":
                               _repA.Delete(a);
                               break;
                     }
                     break;
                 case "B":
                     var b = entity as B;
                     switch (entity.State)
                     {
                          case "Added":
                               _repB.Add(b);
                               break;
                          case "Deleted":
                               _repB.Delete(b);
                               break;
                     }
                     break;
          }
      }
 }

您能建议任何其他解决方案吗? 我考虑了基础 class 和基础存储库的接口。但是在这种情况下,我应该何时以及如何初始化取决于实体类型的 _repo?

 private IBaseRep _repo;

 public void SaveChanges(List<dynamic> entities)
 {
      foreach (var entity in entities)
      {
           switch (entity.State)
           {
               case "Added":
                   _repo.Add(entity)
                   break;
               case "Deleted":
                   _repo.Delete(entity)
                   break;
           }
      }
 }

您的实体 类 AB 违反了 DRY 原则。下面呢?我能想到的一个问题是实体集合的多重枚举,但我不确定你的集合有多大才能知道这是否真的是一个问题。

public abstract class Entity
{
    public Guid Id { get; set; }
    public string Type { get; set; }
    public string State { get; set; }
}

public class A : Entity
{
    public string SomeProperty { get; set; }
}

public class B : Entity
{
    public string AnotherProperty { get; set; }
}

public abstract class Rep<T> where T : Entity
{
    public abstract void Add(T entity);
    public abstract void Delete(T entity);
    public virtual void SaveChanges(IEnumerable<T> entities)
    {
        foreach (var entity in entities)
        {
            switch (entity.State)
            {
                case "Added":
                    Add(entity);
                    break;
                case "Deleted":
                    Delete(entity);
                    break;
                default:
                    throw new InvalidOperationException($"Invalid entity state {entity.State}");
            }
        }
    }
}

public class RepA : Rep<A>
{
    public override void Add(A entity)
    {
        // some specific logic here
    }

    public override void Delete(A entity)
    {
        // some specific logic here
    }
}

public class RepB : Rep<B>
{
    public override void Add(B entity)
    {
        // some specific logic here
    }

    public override void Delete(B entity)
    {
        // some specific logic here
    }
}

public class Program
{
    private static readonly RepA _repA = new RepA();
    private static readonly RepB _repB = new RepB();

    public static void Main()
    {
        var entities = new List<Entity>();

        // fill the list here

        _repA.SaveChanges(entities.OfType<A>());
        _repB.SaveChanges(entities.OfType<B>());
    }
}

visitor pattern 专门用于处理同类列表。