如何解决循环引用问题,例如A类将B类作为其属性之一,而B类将A类作为其属性之一?
如何为这些问题做架构师?
如果以NHibernate为例,对象之间将存在父子关系。
如何处理这些父子场景?
答案 0 :(得分:28)
在大多数情况下,当我必须互相引用两件事时,我创建了一个界面来删除循环引用。例如:
<强> BEFORE 强>
public class Foo
{
Bar myBar;
}
public class Bar
{
Foo myFoo;
}
依赖关系图:
Foo Bar
^ ^
| |
Bar Foo
Foo取决于Bar,但Bar也依赖于Foo。如果它们位于单独的程序集中,则构建时会遇到问题,尤其是在进行干净重建时。
<强> AFTER 强>
public interface IBar
{
}
public class Foo
{
IBar myBar;
}
public class Bar : IBar
{
Foo myFoo;
}
依赖关系图:
Foo, IBar IBar
^ ^
| |
Bar Foo
Foo和Bar都依赖于IBar。没有循环依赖,如果将IBar放在自己的程序集中,Foo和Bar在单独的程序集中将不再是一个问题。
答案 1 :(得分:6)
我会告诉你的朋友他需要重新考虑他的设计。像你描述的循环引用通常是设计缺陷的代码味道。
答案 2 :(得分:5)
与C ++(例如)不同,C#不需要前向声明来解析循环引用。因此:
public class A
{
public B B { get;set; }
}
public class B
{
public A A { get;set; }
}
然而,这通常是可疑设计决策的指标。
答案 3 :(得分:1)
在大多数情况下,最好的解决方案是改变您的设计并避免循环依赖。例如,您可以执行以下操作之一:
但是,如果您正在使用许多项目的解决方案,并且由于您不拥有代码而无法进行上述更改之一,那么它很难实现,或者不值得花时间要修复,那么您可以使用此方法:
右键单击项目引用,然后选择“添加引用...”。然后在出现的对话框窗口中切换到“浏览”选项卡和“浏览”按钮。从那里你可以找到DLL并选择它。这是最好的解决方案,并且可能导致构建问题,尤其是如果两个DLL都经常更新和/或具有许多依赖项。我不推荐这种方法,但它适用于捏。
Fissh
答案 4 :(得分:0)
接口是一个好主意但是如果你寻找一个更快的解决方案,而不是重做这么多东西的架构,试着构建一个包含所有数据结构的dll类库,你的主项目会保存你需要该数据的UI,然后是其他任何你想要添加的dll也可以访问那些数据结构dll,因此它们具有运行所需的所有信息,但仍然可以分开 - 这称为三力设计模式 -
答案 5 :(得分:0)
当两个或更多相互依赖的资源导致锁定条件时,发生循环引用。这使资源无法使用。
要处理C#中的循环引用问题,应使用垃圾回收。它检测并收集循环引用。垃圾收集器从局部和静态开始,并标记可以通过其子级访问的每个对象。
通过此操作,您可以使用循环引用来解决问题。
假设以下类是循环引用。在这里,他们彼此依赖-
public class A
{
B Two;
}
public class B
{
A one;
}
要解决此问题,请创建一个接口-
public interface myInterface {
}
public class A {
myInterface Two;
}
public class B: myInterface {
A one;
}