标题说“ Circular Dependency”,但这不是正确的措辞,因为对我来说,设计似乎很牢固。
但是,请考虑以下情形,其中蓝色部分由外部合作伙伴提供,橙色是我自己的实现。还假设有多个ConcreteMain
,但我要使用一个特定的。(实际上,每个类都有更多的依赖关系,但是我在这里尝试简化它)
我想通过Depency Injection(Unity)实例化所有这些,但是我显然可以StackOverflowException
在以下代码上找到,因为Runner试图实例化ConcreteMain,而ConcreteMain需要一个Runner。
IUnityContainer ioc = new UnityContainer();
ioc.RegisterType<IMain, ConcreteMain>()
.RegisterType<IMainCallback, Runner>();
var runner = ioc.Resolve<Runner>();
我该如何避免呢?有什么方法可以构造它,以便可以与DI一起使用?我现在正在执行的方案是手动设置所有内容,但这ConcreteMain
在实例化它的类中具有硬性依赖。这就是我要避免的事情(在配置中使用Unity注册)。
下面的所有源代码(非常简化的示例!);
public class Program
{
public static void Main(string[] args)
{
IUnityContainer ioc = new UnityContainer();
ioc.RegisterType<IMain, ConcreteMain>()
.RegisterType<IMainCallback, Runner>();
var runner = ioc.Resolve<Runner>();
Console.WriteLine("invoking runner...");
runner.DoSomethingAwesome();
Console.ReadLine();
}
}
public class Runner : IMainCallback
{
private readonly IMain mainServer;
public Runner(IMain mainServer)
{
this.mainServer = mainServer;
}
public void DoSomethingAwesome()
{
Console.WriteLine("trying to do something awesome");
mainServer.DoSomething();
}
public void SomethingIsDone(object something)
{
Console.WriteLine("hey look, something is finally done.");
}
}
public interface IMain
{
void DoSomething();
}
public interface IMainCallback
{
void SomethingIsDone(object something);
}
public abstract class AbstractMain : IMain
{
protected readonly IMainCallback callback;
protected AbstractMain(IMainCallback callback)
{
this.callback = callback;
}
public abstract void DoSomething();
}
public class ConcreteMain : AbstractMain
{
public ConcreteMain(IMainCallback callback) : base(callback){}
public override void DoSomething()
{
Console.WriteLine("starting to do something...");
var task = Task.Factory.StartNew(() =>{ Thread.Sleep(5000);/*very long running task*/ });
task.ContinueWith(t => callback.SomethingIsDone(true));
}
}