【问题标题】:Castle Windsor: Reuse resolved component in OnCreate, UsingFactoryMethod or DynamicParametersCastle Windsor:在 OnCreate、UsingFactoryMethod 或 DynamicParameters 中重用已解析的组件
【发布时间】:2010-04-30 19:30:20
【问题描述】:

我正在尝试在已解析的组件作为应用程序的依赖项返回之前对其执行操作。

例如,用这个图表:

public class Foo : IFoo { }

public class Bar {
  IFoo _foo;
  IBaz _baz;
  public Bar(IFoo foo, IBaz baz) {
    _foo = foo;
    _baz = baz;
  }
}

当我创建 IFoo 的实例时,我希望容器实例化 Bar 并将已解析的 IFoo 以及它所需的任何其他依赖项传递给它。所以当我打电话时:

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

容器应该自动调用:

container.Resolve<Bar>(); // should pass foo and instantiate IBaz

我尝试过使用 OnCreate、DynamicParameters 和 UsingFactoryMethod,但它们都有一个共同的问题是它们没有对组件进行显式引用: 在实例化 IFoo 之前调用 DynamicParameters。 OnCreate 之后被调用,但委托没有传递实例。 UsingFactoryMethod 没有帮助,因为我需要使用 TService 和 TComponent 注册这些组件。

理想情况下,我希望注册看起来像这样:

container.Register<IFoo, Foo>((kernel, foo) => kernel.Resolve<Bar>(new { foo }));

请注意,IFoo 和 Bar 是使用瞬态生活方式注册的,这意味着必须将已解析的实例传递给 Bar - 它不能“重新解析”。

这可能吗?我错过了什么吗?

【问题讨论】:

  • IIRC OnCreate 确实传递了实例。
  • 你是对的。我不知道我是怎么错过的。但我仍然无法自动解析 Bar 。将此 'container.Resolve(new { foo = instance })' 传递给 OnCreate 是创建 foo 的新实例,而不是使用已解析的实例。我认为这是因为短暂的生活方式。
  • 我不明白你为什么要在实际解析 IFoo 时解析 Bar。你要么想要 IFoo,要么想要 Bar。
  • 应用程序请求一个 IFoo:container.Resolve()。但它的工作方式是必须创建一个 Bar 来包装、管理和初始化 IFoo 实例,然后再将其返回给应用程序。没有对象会持有对 Bar 的引用:一旦 IFoo 实例被释放,它将被 GC。

标签: castle-windsor ioc-container


【解决方案1】:

看来这就是你想要的:

public interface IFoo {}
public class Foo : IFoo {}
public class Bar {
    public IFoo BarFoo { get; private set;}

    public Bar(IFoo foo) {
        BarFoo = foo;
    }

    public void DoSomething() {
        Console.WriteLine("Initializing");
    }
}

[Test]
public void Create() {
    var container = new WindsorContainer();
    var initialized = false;
    container.Register(Component.For<IFoo>().ImplementedBy<Foo>().LifeStyle.Transient
        .OnCreate((kernel, foo) => {
            var bar = kernel.Resolve<Bar>(new {foo});
            Assert.AreSame(foo, bar.BarFoo);
            bar.DoSomething();
            initialized = true;
        }));
    container.Register(Component.For<Bar>().LifeStyle.Transient);
    var f = container.Resolve<IFoo>();
    Assert.IsTrue(initialized);
}

它实际上几乎是this other question的复制品。

【讨论】:

  • 我试过类似的代码。这里的期望是传递匿名 [new {foo}] 将避免在解析 Bar 时创建解析新的 IFoo 实例,但我的经验不同。容器不断创建新的 IFoo 实例。也许我做错了什么。我会再试一次并告诉你。
  • 顺便说一句,我看到了另一个问题,但有几个显着的区别: 1. 在 IFoo 解决后,我不需要对 Bar 实例进行显式引用。 2. Bar 依赖于瞬态 IFoo 以及全局 IBaz。
  • 我已经弄明白了。您的代码最初产生了循环依赖错误。问题是我忘了考虑温莎的财产注入,因为 BarFoo(在现实生活中)有一个公共设置器。一旦我添加了 OptionalPropertyInjectionFacility,你的代码就可以工作了。
  • @shovanik:代码对我有用,就像我发布的一样。测试通过。
猜你喜欢
  • 2018-02-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-06
  • 2014-08-18
  • 1970-01-01
  • 2016-02-26
  • 1970-01-01
相关资源
最近更新 更多