c# - 持久层和业务逻辑调用c#的多态性问题
问题描述
我实际上正在学习多态性。我使用 DAO 模式将我的业务逻辑与持久层完全解耦,但现在我在尝试访问持久层中的业务数据时遇到了一个问题。
我给你举个简单的例子
public class A
{
}
public class B : A
{
}
public class C : A
{
}
public class D : A
{
}
class Program
{
protected virtual void Main(string[] args)
{
List<A> alist = new List<A>
{
new B(),
new C(),
new D()
};
PersistenceLayer persistenceLayer = new PersistenceLayer();
foreach (A a in alist)
{
persistenceLayer.Foo(a); // can't call it
}
}
public class PersistenceLayer
{
public void Foo(B b)
{
Console.WriteLine("is B");
}
public void Foo(C c)
{
Console.WriteLine("is c");
}
public void Foo(D d)
{
Console.WriteLine("is d");
}
}
}
我需要循环通用类,这就是我以列表形式拥有的,这就是我可以通过我的业务类控制器获得的。现在要获取子类类型并调用适当的方法,我需要为下一个更改 foreach。
foreach (A a in alist)
{
if (a is B b)
{
persistenceLayer.Foo(b);
}
else if (a is C c)
{
persistenceLayer.Foo(c);
}
else if (a is D d)
{
persistenceLayer.Foo(d);
}
}
所以现在它可以工作了,但是我讨厌 switch 或 ifs 检查类型和调用方法,因为现在我有 3 个子类,但是 20 个子类型会发生什么?
有没有办法做到这一点而不做这个 ifs 或 switch?也许有一些模式?
解决方案
这看起来像是访问者模式的完美用例。
public interface IPersistenceLayer
{
// These methods could all be called 'Foo' without the 'A' 'B' or 'C' suffix, but I've appended it to make it clear which method is being called
void FooB(B b);
void FooC(C c);
void FooD(D d);
}
// I've made 'A' abstract, because in your example there is no 'Foo(A a)' method so this can't provide a default 'Foo' implementation
public abstract class A
{
public abstract void Foo(IPersistenceLayer persistenceLayer);
}
public class B : A
{
public override void Foo(IPersistenceLayer persistenceLayer) => persistenceLayer.FooB(this);
}
public class C : A
{
public override void Foo(IPersistenceLayer persistenceLayer) => persistenceLayer.FooC(this);
}
public class D : A
{
public override void Foo(IPersistenceLayer persistenceLayer) => persistenceLayer.FooD(this);
}
public static class PersistenceLayerExtensions
{
public static void Foo(this IPersistenceLayer persistenceLayer, A a) => a.Foo(persistenceLayer);
}
class Program
{
public static void Main(string[] args)
{
List<A> alist = new List<A>
{
new B(),
new C(),
new D()
};
PersistenceLayer persistenceLayer = new PersistenceLayer();
foreach (A a in alist)
{
persistenceLayer.Foo(a);
}
}
}
推荐阅读
- keycloak - Keycloak - 使用 Rest API 验证用户的电子邮件
- python - Django url 问题没有加载我的 html 模板
- reactjs - 我无法使用 getDerivedStateFromProps 更新状态
- java - 在Android中拖动recyclerview项目时在溢出前开始滚动
- python - 如何使用 pd.read_csv() 下载嵌入为图像的文件?
- c - 如何将器官添加到C中链表中的特定位置
- php - 重命名键名codeigniter
- ruby-on-rails - 带有设计的 icalendar gem 的问题
- visual-studio-code - VSCode中的自定义不可见字符渲染?
- python - welcoming new members, member has no attribute 'server'