簡體   English   中英

ninject 的循環依賴

[英]Cyclic dependency with ninject

我正在嘗試找出如何使用 ninject 綁定此類內容的正確方法。

interface IMainService
{
    void DoStuff();
}

interface IOtherService
{
    void DoSomeMagic();
}

abstract class BaseClass
{
    //many stuff here
}

class MainClass : BaseClass, IMainService
{
    public MainClass(IOtherService s)
    {
    }

    public void DoStuff()
    {
        throw new NotImplementedException();
    }

    //do many other things
}

class OtherClass : IOtherService
{
    public OtherClass(IMainService s)
    {
    }

    public void DoSomeMagic()
    {
        throw new NotImplementedException();
    }
}

class BaseModule : NinjectModule
{
    public override void Load()
    {
        Bind<MainClass>().To<MainClass>();
        Bind<IMainService>().To<MainClass>();
        Bind<IOtherService>().To<OtherClass>();
    }
}

static class Program
{
    static void Main()
    {
        var kernel = new StandardKernel(new BaseModule());
        var main = kernel.Get<MainClass>();
    }
}

它給了我例外:

Error activating IOtherService using binding from IOtherService to OtherClass
A cyclical dependency was detected between the constructors of two services.

Activation path:
  4) Injection of dependency IOtherService into parameter s of constructor of type MainClass
  3) Injection of dependency IMainService into parameter s of constructor of type OtherClass
  2) Injection of dependency IOtherService into parameter s of constructor of type MainClass
  1) Request for MainClass

Suggestions:
  1) Ensure that you have not declared a dependency for IOtherService on any implementations of the service.
  2) Consider combining the services into a single one to remove the cycle.
  3) Use property injection instead of constructor injection, and implement IInitializable if you need initialization logic to be run after property values have been injected.

我不知道如何編寫 BaseModule。 我只需要一個 MainClass 實例和一個 OtherClass 實例(如單例)。

我試過這樣的事情:

Bind<MainClass>().To<MainClass>().InSingletonScope();
Bind<IMainService>().To<MainClass>().InRequestScope();
Bind<IOtherService>().To<OtherClass>().InSingletonScope();

但有同樣的錯誤。

以及如何編寫僅使用 MainClass 和 IMainService 接口的一個實例的綁定?

感謝您的回答。

如錯誤消息所述, MainClassOtherClass之間具有循環依賴關系,因為如果沒有其他實例則無法創建一個。 理想情況下,您應該重組您的類層次結構以消除此要求。

如果不能,解決方案是對一個(或兩個)類使用屬性注入,例如

public interface IMainService
{
    void DoStuff();
    IOtherService OtherService { set; }
}

public class MainClass
{
    public IOtherService OtherService { get; set; }
    public void DoStuff() { ... }
}

public class OtherService
{
    public OtherService(IMainService main)
    {
        main.OtherService = this;
    }
}

我認為您不應為此使用屬性或setter方法,最好使用惰性。 懶惰的概念解決了這個問題。 問題是,如果對象之間具有循環依賴關系,則不清楚創建第一個對象的方式。 懶惰的解決方法是:一旦真正使用了對象(通常,在調用公共方法時就是這種情況,它就必須存在)。 如果可能的話,請避免使用屬性或二傳手。 它們使您的對象可變(對線程安全不利,在僅應注入依賴項一次時不需要)。

您的構造函數應如下所示:

public OtherService(Lazy<IMainService> main)
{
    this.main = main;
}

public MainClass(Lazy<IOtherService> s)
{
    this.s = s;
}

您可以通過調用“ ToMethod(”基於get方法創建Lazy方法的labda方法“),使用Load方法在Ninject模塊中描述這些惰性依賴關系。

這里展示了一個清晰的示例,展示了如何通過Ninject解決惰性問題。 它還描述了一個幫助方法(BindLazy)來解決您的問題。 https://www.codeproject.com/Tips/1171940/How-Ninject-Can-Help-in-Resolution-Circular-Depende

您也可以使用改進的屬性來解決它,以避免不需要訪問設置器:

public interface IMainService
{
    void DoStuff();
}

public class MainClass
{
    [Inject] public IOtherService OtherService { get; init; }
    public void DoStuff() { ... }
}

public class OtherService
{
    public OtherService(IMainService main)
    {
        main.OtherService = this;
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM