我一直在努力重构一个应用程序,以便通过依赖注入和所有好东西使其更易于管理。这样做时,我不止一次遇到过循环依赖。
所以这是循环依赖的典型例子:
interface IA
{
int Data { get; }
}
interface IBefore
{
void DoStuffBefore();
}
class A: IA
{
public int Data { get; private set; }
IBefore before;
public A(IBefore before)
{
this.before = before;
}
public void Increment()
{
before.DoStuffBefore();
Data++;
}
}
class B: IBefore
{
IA a;
public B(IA a)
{
this.a = a;
}
public void WriteADataToConsole()
{
Console.Write(a.Data);
}
public void DoStuffBefore() //From IBefore
{
WriteADataToConsole();
}
}
我不能创建任何类,因为它们需要彼此。现在,在这种情况下要做的标准(?)事情是将A的数据与A:
分开public interface IA
{
int Data { get; set; }
}
public interface IBefore
{
void DoStuffBefore();
}
class AData : IA
{
public int Data { get; set; }
}
class A
{
public IA Data { get; private set; }
IBefore before;
public A(IA data, IBefore before)
{
this.Data = data;
this.before = before;
}
public void Increment()
{
before.DoStuffBefore();
Data.Data++;
}
}
class B : IBefore
{
IA a;
public B(IA a)
{
this.a = a;
}
public void WriteADataToConsole()
{
Console.Write(a.Data);
}
public void DoStuffBefore() //From IBefore
{
WriteADataToConsole();
}
}
上面解决了循环依赖,因为我现在可以先创建AData,然后将其注入B并将B注入A.但我也可以放置一个B可以收听的事件:
public interface IA
{
int Data { get; }
event Action BeforeEvent;
}
class A: IA
{
public int Data { get; private set; }
public event Action BeforeEvent;
public void Increment()
{
BeforeEvent();
Data++;
}
}
class B
{
IA a;
public B(IA a)
{
this.a = a;
a.BeforeEvent += new Action(WriteADataToConsole);
}
void WriteADataToConsole() //Event listener
{
Console.Write(a.Data);
}
}
这是我偶然发现的声音,因为我试图将事件方法转换为依赖注入,并意识到通过这样做我已经得到了循环依赖。
一些困扰我大脑的问题是:
答案 0 :(得分:2)
好问题!在95%的情况下,你必须将这两个实体合并在一起,或者以其他方式破坏依赖关系,但是......如果因为某种原因而无法合并为一个实体(使用UI)该怎么办?有时可能会这么棘手)?有一本关于"Dependency Injection in .NET" by Mark Seemann的书,其中介绍了两种打破循环依赖关系的方法:
在第二个带属性的实现中,有一个构造函数:public A(IA data, IBefore before)
。在依赖注入方面,IA data
和IBefore before
都是必需的 - 这是对breack cicle的最佳观点!这是一个带有可选IBefore
的实现:
class A
{
public IA Data { get; private set; }
public IBefore Before { get; set; }
public A(IA data)
{
this.Data = data;
}
public void Increment()
{
// here should be design decision: if Before is optional…
if(Before == null)
{
Before.DoStuffBefore();
}
// …or required
if(Before == null)
{
throw new Exception("'Before' is required");
}
Data.Data++;
}
}
由您自行决定,如果Before.DoStuffBefore()
是可选的,可以跳过Before
来电,如果需要则提出异常
根据你的问题: