如何避免嵌套开关结构?
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;
}
}
}
您的实体 类 A
和 B
违反了 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 专门用于处理同类列表。
比如我有两个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;
}
}
}
您的实体 类 A
和 B
违反了 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 专门用于处理同类列表。