제목에 "순환 종속성"이라고 표시되어 있지만 디자인이 견고 해 보이기 때문에 올바른 표현이 아닙니다.
그러나 파란색 부분이 외부 파트너에서 제공되고 주황색이 내 구현 인 다음 시나리오를 고려하십시오. 또한 하나 이상이 있다고 가정 ConcreteMain
하지만 특정 것을 사용하고 싶습니다. (실제로 각 클래스에는 더 많은 종속성이 있지만 여기서 단순화하려고했습니다.)
Depency Injection (Unity)을 사용 하여이 모든 것을 설명하고 싶지만 StackOverflowException
Runner가 ConcreteMain을 인스턴스화하려고 시도하고 ConcreteMain에 러너가 필요하기 때문에 분명히 다음 코드를 얻습니다 .
IUnityContainer ioc = new UnityContainer();
ioc.RegisterType<IMain, ConcreteMain>()
.RegisterType<IMainCallback, Runner>();
var runner = ioc.Resolve<Runner>();
어떻게 이것을 avouid 수 있습니까? 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));
}
}