在Ninject中,在单例范围内声明绑定意味着每次都会返回相同的对象。永远只能有一个对象。
我想要的是一次返回一个对象。换句话说:
编辑:使用providers解决此问题实际上非常简单,并且在处置时让相关对象引发事件。我很好奇是否有办法在Ninject中使用范围进行此操作,并且会在此留下这个问题,因为史蒂文的答案非常好。
答案 0 :(得分:6)
由于您希望在多线程应用程序中使用此构造并希望跨线程重用相同的实例(正如您在注释中所暗示的那样),因此您将无法通过配置DI容器来解决此问题。 / p>
由于竞争条件,您无法在处置后配置要续订的对象。想象一下以下场景:
Dispose
。问题是应用程序将获得对可以处理的实例的引用。
如果可以的话,尽量通过重新设计应用程序来防止这样做。公开实现IDisposable
的服务类型是一种不好的做法,因为IDisposable
是一个漏洞抽象。我个人的偏好甚至是阻止这些服务的任何实现来实现IDisposable
。在大多数情况下,重新设计可以防止您不必这样做。
如果需要使用IDisposable
个对象,通常的做法是创建和注入创建这些IDisposable
个对象的工厂。通过这种方式,消费者可以毫无问题地安全地处理这样的物体。
这里的一般问题是很难创建实现IDisposable
的对象,这些对象实际上是线程安全的。
如果你真的想要这个,你可以尝试创建一个引用计数的装饰器。在下面的装饰器中查找实例。它包装IService
并实现IService
。 IService
实施IDisposable
。装饰者需要Func<IService
&gt;允许创建实例的委托。对象的创建和处理受lock
语句的保护,并且装饰器计算调用者对它的引用。在最后一个消费者处理装饰器之后,它将处理该对象并创建一个新对象。
public class ScopedServiceDecorator : IService
{
private readonly object locker = new object();
private Func<IService> factory;
private IService currentInstance;
private int referenceCount;
public ScopedServiceDecorator(Func<IService> factory)
{
this.factory = factory;
}
public void SomeOperation()
{
IService instance;
lock (this.locker)
{
instance = this.GetInstance();
this.referenceCount++;
}
instance.SomeOperation();
}
public void Dispose()
{
IService instance = null;
lock (this.locker)
{
this.referenceCount--;
if (this.referenceCount == 0)
{
instance = this.wrappedService;
this.wrappedService = null;
}
}
// Dispose the object outside the lock for performance.
if (instance != null)
{
instance.Dispose();
}
}
private IService GetInstance()
{
if (this.wrappedService == null)
{
this.wrappedService = this.factory();
}
return this.wrappedService;
}
}
请注意,由于以下原因,此实施仍存在缺陷:
Dispose
会破坏装饰者。SomeOperation
时(或IService
有多种方法),实施将会中断。创建一个按预期运行的装饰器非常困难。一种简单的方法是序列化对象的访问,但是当你这样做时,你可能想要为每个线程使用一个实例。那会容易得多。
我希望这会有所帮助。
答案 1 :(得分:1)
我知道这已经解决了但是...... @ Steven的回答并没有指出Ninject中有一个InScope
机制来解决你正在寻找的方面。
请看Nate Kohari的Cache and Collect文章,了解如何在Ninject 2中完成范围界定。
接下来,查看ninject源代码,了解InRequestScope的实现方式(包括如何连接拆卸)。有一些工作计划用于2.3-4,以概括它如何工作以允许它用于一些复杂的托管场景。
当您查看这两个参考文献时,请在ninject邮件列表上提问,您肯定会有解决方案。