【问题标题】:Castle dependency injection LifestyleCastle 依赖注入 Lifestyle
【发布时间】:2012-03-22 04:49:01
【问题描述】:

我应该指出,我对 Castle 比较陌生,所以还不知道我在用它做什么。要点是,我正在尝试使用 Castle Windsor 制作对象的自定义生命周期。我不完全确定应该如何做到这一点,但是,我能找到的最接近它应该如何工作的近似值我在下面详细说明。

我想要一个单例,但我无法释放此类型并为其分配新实例。

即,

public interface IMyObject { string text; }

public class MyObject() : IMyObject    {
    public string text;
}

var container = new WindsorContainer();
container.Register(Component.For<IMyObject>().ImplementedBy<MyObject>().LifeStyle.Singleton);

MyObject item = SomeMethodGetInstance(); //Defines scope for instance 1
item = container.Resolve<IMyObject>(item);
Print(item);     

>>instance 1
....

item = container.Resolve<IMyObject>();  //gets instance 1
Print(item); 
>>instance 1
....

item = SomeMethodGetInstance()  //New scope defined, now using instance 2

我希望能够释放该实例,但 Windsors 对 Singleton 的定义对于我的需求来说过于死板。

container.Release(item);    //I need to release the current instance, this doesn't work.

container.Kernal.ReleaseComponent(item);  //Don't work either.

因此,当我将新项目设置为当前项目时,它不会恢复为实例 1。

item = container.Resolve<IMyObject>(item);  //sets the currect instance of MyObject
Print(item); 

>>instance 2

我需要存储一个具有自定义作用域的变量,Singleton 或 Transient 都不会为我解决问题。当存储的变量进出范围时,我需要能够定义范围。

更重要的是,如果我有另一个类B,它依赖于A,那么如果我从容器外部获取A,我如何在容器中设置A?这在单例场景中很好,但我无法为瞬态场景设置它,但是,对于单例,一旦设置,我就无法释放它,这是必要的。

请问我该怎么做?

我想在代码中而不是在 xml 中执行此操作,因为我正在动态注册类。

【问题讨论】:

标签: c# .net dependency-injection castle-windsor


【解决方案1】:

您可以将您的组件注册为单个组件,如下所示

public void Register(string name, Type service, Type impl)
{
   WindsorContainer container = new WindsorContainer();
   IKernel kernel = container.Kernel;
   kernel.AddComponent(name, service, impl, LifestyleType.Singleton);
}

你可以按如下方式释放组件

kernel.ReleaseComponent(yourResolvedSingletonInstance)

【讨论】:

  • 无法释放单例。我尝试了您建议的注册实现,但是它不起作用,温莎不喜欢这个名字。
【解决方案2】:

我想要单身

温莎城堡的默认生活方式单身。

但我无法释放此类型并为其分配新实例。

但那不是单例。

请问我该怎么做?

您没有具体说明您想要做什么。每次调用Resolve 时都需要一个新实例吗?那是LifeStyle.Transient

【讨论】:

  • 这不是单例,也不是瞬态,它是灰色阴影。我正在使用从数据库中检索的对象。我很清楚,我的实现有点糟糕,但是,这是我需要的。最接近的近似值是 perWebRequest,但我没有使用 http。
  • 您没有指定您需要什么。您需要准确描述它。你显然没有说清楚,因为你说你想要一个单身人士,但你没有。您的代码表明它应该是瞬态的,但您说不是。
  • 我有一个数据库调用,这得到一个对象,从技术上讲它是瞬态的,但是我不能将它注入其他类,因为它被标记为瞬态,每次都会创建一个新实例,这会失败首先是数据库调用。我不能将对象标记为单例,因为我不能多次获取该项目,因为我不能释放它。
  • 为什么要将依赖注入与从数据库调用中获取的对象混合在一起?那是你困惑的很大一部分。
  • 因为类对数据库实体有依赖。见谅,这不是依赖注入的意思吗?
【解决方案3】:

您是否考虑过使用自定义工厂来生产您的实例?它可以在需要时调用 DI 框架来生成新实例,但您可以定义自己的逻辑来确定何时需要释放旧实例。

这种方法也回答了您的第二个问题。 B 类不应将 A 作为依赖项,而应将 AFactory 视为依赖项。因为B 可能比A 寿命更长,所以每次使用时都需要向工厂询问A 的“当前”实例。

【讨论】:

  • 这可能是前进的方向。
  • 不,不是!您不需要 DI 容器来从数据库中获取数据,然后将其传递给该数据的使用者。你只是让事情变得不必要地复杂化,什么也不给自己买。我怀疑 StriplingWarrior 的回答是在他知道您打算使用它的上下文之前做出的。
  • 这对我来说非常沮丧,这是我所知道的。
  • @Craig:杰森说得对。听起来你真正想要的是一个缓存的存储库,而不是注入这个具有特定生命周期的对象。最终,它可能会以与我推荐的 Factory 非常相似的方式工作,但由于您正在生成一条数据而不是服务,因此“Repository”是比“Factory”更合适的名称。您将清除缓存的数据,而不是“释放”实例。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-10
  • 2020-06-21
  • 2023-03-23
  • 1970-01-01
  • 2012-09-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多