4

我有两个需要相互引用的类。

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

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

当我做:

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

当我尝试解析任一接口时,我得到一个循环依赖图,导致无限循环。有没有简单的方法可以在 Funq 中解决这个问题,或者你知道解决方法吗?

4

6 回答 6

7

您总是可以(并且在所有容器中,我会说)依赖 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>());
于 2012-09-09T21:05:09.753 回答
1

你的问题的答案是否定的,没有简单的方法。鉴于上面的代码,没有Funq就不可能构造任何一个类,因此没有理由期望 Func 能够做到。

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

当然,如果您有另一个实现,IFoo或者IBar没有依赖,或者您进行了重构,这可能是可能的。

于 2012-09-06T20:08:09.457 回答
1

一般来说,“在进行依赖注入时如何分解循环引用”这个问题的答案是:“使用属性注入”。

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;
});

此外,我同意 Tim Rogers 的评论。当你有循环依赖时,你的设计可能有问题,你应该看看它。这并不总是错误的,但经常是。但是,您展示的代码非常抽象,我们无法对此提供任何反馈。

于 2012-09-07T22:00:02.410 回答
0

这对我有用:

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 的观​​点——循环引用是一个需要解决的问题。

于 2012-09-06T15:29:19.097 回答
0

在容器中注册您的类型后,使容器可用作静态变量:

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()
  {
  }

}
于 2012-09-07T08:43:53.427 回答
0

我有一个类似的场景,两个类之间的依赖关系让我意识到它们实际上应该组合成一个类。

于 2017-07-23T18:46:20.510 回答