簡體   English   中英

如何在Funq IoC中解決循環依賴?

[英]How can I resolve circular dependencies in Funq IoC?

我有兩個課程,我需要互相參考。

class Foo
{
    public Foo(IBar bar) {}
}

class Bar
{
    public Bar(IFoo foo) {}
}

當我做:

container.RegisterAutoWiredAs<Foo, IFoo>();
container.RegisterAutoWiredAs<Bar, IBar>();

當我嘗試解決任一接口時,我得到一個循環依賴圖,導致無限循環。 有沒有一種簡單的方法可以在Funq中解決這個問題,或者您知道一種解決方法嗎?

您總是可以(並且在所有容器中,我會說)依賴Lazy作為依賴,這將產生所需的結果。 在Funq:

public Bar(Lazy<IFoo> foo) ...
public Foo(Lazy<IBar> bar) ...

container.Register<IBar>(c => new Bar(c.LazyResolve<IFoo>());
container.Register<IFoo>(c => new Foo(c.LazyResolve<IBar>());

你的問題的答案是否定的,沒有簡單的方法。 鑒於上面的代碼, 沒有 Funq就不可能構造任何一個類,所以沒有理由期望Func能夠做到這一點。

var foo = new Foo(/* what do I pass here? */);
var bar = new Bar(foo);

當然,如果你有一個沒有依賴的IFooIBar另一個實現,或者你重構,它可能是可能的。

一般來說,“在執行依賴注入時如何分解循環引用”這一問題的答案是:“使用屬性注入”。

class Foo
{
    public Foo() {}

    // Break the dependency cycle by promoting IBar to a property.
    public IBar Bar { get; set; }
}

class Bar
{
    public Bar(IFoo foo) {}
}

使用Funq我認為這將是注冊此依賴項的方法。

container.Register<IBar>(c =>
{
    var foo = new Foo();
    var bar = new Bar(foo);
    foo.Bar = bar;
    return bar;
});

此外,我同意蒂姆羅傑斯的評論。 當你有一個循環依賴,你的設計可能有一個問題,你應該看看它。 這並不總是錯的,但往往是錯的。 但是,您展示的代碼非常抽象,我們無法就此提供任何反饋。

這對我有用:

using Funq;
using NUnit.Framework;

namespace FunqIoCyclicReferenceTest
{
    [TestFixture]
    public class FunqIoCCyclicReferenceTest
    {
        [Test]
        public void Please_Work()
        {
            var container = new Container();
            container.Register<IBar>(c => new Bar());
            container.Register<IFoo>(c => new Foo(c.Resolve<IBar>()));

            var foo = container.Resolve<IFoo>();

            Assert.IsNotNull(foo);
        }
    }

    public class Foo : IFoo
    {
        public Foo(IBar bar)
        {
            bar.Foo = this;
            Bar = bar;
        }

        public IBar Bar { get; set; }
    }

    public interface IBar
    {
        IFoo Foo { get; set; }
    }

    public interface IFoo
    {
        IBar Bar { get; set; }
    }

    public class Bar : IBar
    {
        public IFoo Foo { get; set; }
    }
}

編輯
同樣的想法,但在構造函數中沒有副作用:

// interfaces
public interface IBar
{
    IFoo Foo { get; set; }
}

public interface IFoo
{
    IBar Bar { get; set; }
}

// implementations
public class Foo : IFoo
{
    public IBar Bar { get; set; }
}    

public class Bar : IBar
{
    public IFoo Foo { get; set; }
}

// usage
container.Register<IBar>(c => new Bar());
container.Register<IFoo>(c => 
{
    var bar = c.Resolve<IBar>();
    var foo = new Foo();

    bar.Foo = foo;
    foo.Bar = bar;
});

ps但我同意Tim Rogers的說法 - 循環引用是一個需要解決的問題。

在容器中注冊類型后,使容器可用作靜態變量:

public static class ContainerHolder
{
   public static Container Container {get;set;}
}

public class Foo : IFoo
{
  private IBar _bar;

  public Foo(IBar bar)
  {
    _bar = bar;
  }
}

public class Bar : IBar
{
  private IFoo _foo
  {
    get { return ContainerHolder.Container.Resolve<IFoo>(); }
  }

  public Bar()
  {
  }

}

我有一個類似的場景,兩個類之間的依賴關系使我意識到它們實際上應該合並為一個類。

暫無
暫無

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

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