昨天在工作中遇到一个非常有趣的问题。
我有两个名为Foo和Bar的不同类。每个人都坐在自己的C#库项目中(单独的dll)。
Bar包含一个虚拟方法:
public class Bar
{
public virtual void DoSomething();
}
Foo在其构造函数中使用Bar实例来设置内部属性:
public Foo (Bar myBar)
{
m_Bar = myBar;
}
显然,Foo提到了Bar的项目。
现在,我有另外5个类,每个类也都位于自己的项目/ dll中。我们将它们称为A,B,C,D和E. A-E都是类Bar的子类,每个都包含它们自己的DoSomething()重写实现。因为它们是从Bar子类化的,所以它们中的任何一个都可以作为Foo构造函数的参数。
A-E各自维护一个Foo实例的内部集合。例如,我会在A类中做这样的事情:
myFooCollection.Add(new Foo(this));
因此,A-E类都需要引用Foo的项目/ dll。
现在,切换回Foo片刻让我们说在构造函数中设置Bar属性之后我需要调用该Bar的DoSomething()方法:
public class Foo (Bar myBar)
{
m_Bar = myBar;
m_Bar.DoSomething();
}
请记住,例如,A类被用作构造函数的Bar参数。我对DoSomething()的调用需要执行该方法的A实现。但是,由于构造函数参数是父类Bar,而Foo不知道类A-E(我不能在不引起循环依赖的情况下给它引用),它将在父类Bar中调用虚方法。在拨打电话之前,自然的解决方案是向子班级投降:
(A)m_Bar.DoSomething();
但这也是不可能的,因为再一次,Foo不知道这组子类。所以这就是我的困境。整个项目结构无法改变,因为系统显然比我在这里展示的更大更复杂。但我的要求仍然相同。 Foo需要能够到达DoSomething()的子实现才能正常运行。有关如何解决这个问题的任何想法?如果需要澄清以更好地理解问题,请告诉我,我会进一步详细说明。
答案 0 :(得分:3)
您不得拥有项目的静态循环引用;但是,您可以拥有实例的动态循环引用。如果你调用m_Bar.DoSomething();
那么,由于多态性,将自动调用正确的实现。如果m_Bar
是Bar
,则会调用Bar
的实现。如果m_Bar
是A
,则会调用A
的实现。 Bar
和Foo
都不需要知道类A
到E
的现有内容。
更新:(见下面的评论)
public class A : Bar
{
public override void DoSomething()
{
Console.WriteLine("I am an 'A'");
}
}