शीर्षक "सर्कुलर डिपेंडेंसी" कहता है, लेकिन यह सही शब्द नहीं है, क्योंकि मेरे लिए डिज़ाइन ठोस लगता है।
हालांकि, निम्नलिखित परिदृश्य पर विचार करें, जहां बाहरी हिस्से से नीले रंग के हिस्से दिए गए हैं, और नारंगी मेरा अपना कार्यान्वयन है। इसके अलावा मान लें कि एक और है ConcreteMain
, लेकिन मैं एक विशिष्ट का उपयोग करना चाहता हूं। (वास्तव में, प्रत्येक वर्ग की कुछ और निर्भरताएँ होती हैं, लेकिन मैंने इसे यहाँ सरल बनाने की कोशिश की है)
मैं डिप्रेशन इंजेक्शन (एकता) के साथ इस सब को भड़काना चाहूंगा, लेकिन मुझे स्पष्ट रूप StackOverflowException
से निम्नलिखित कोड मिलता है, क्योंकि रनर कंक्रीटमैने को तुरंत करने की कोशिश करता है, और कंक्रीटमैन को एक रनर की आवश्यकता होती है।
IUnityContainer ioc = new UnityContainer();
ioc.RegisterType<IMain, ConcreteMain>()
.RegisterType<IMainCallback, Runner>();
var runner = ioc.Resolve<Runner>();
मैं इसे कैसे प्राप्त कर सकता हूं? क्या इसकी संरचना का कोई तरीका है ताकि मैं इसे DI के साथ उपयोग कर सकूं? अब मैं जो परिदृश्य कर रहा हूं, वह सब कुछ मैन्युअल रूप से सेट कर रहा है, लेकिन यह ConcreteMain
उस वर्ग पर एक कठिन निर्भरता रखता है जो इसे तुरंत करता है। यही मैं बचने की कोशिश कर रहा हूं (कॉन्फ़िगरेशन में एकता पंजीकरण के साथ)।
नीचे सभी स्रोत कोड (बहुत सरल उदाहरण!);
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));
}
}