温莎城堡临时一次性用品
我知道这已经被讨论得令人作呕......但我对 Windsor 跟踪瞬态 IDisposable 对象的方式有疑问。
我了解让 Windsor 管理我的 IDiposables 的好处...但我不喜欢它。
如果我想将组件包装在 using 块中会发生什么?编码器会假设资源将在 using 块结束时被清理,对吗?错误 - 将调用 Dispose,但 Windsor 会保留该实例,直到显式释放为止。这对我来说一切都很好,因为我知道我在做什么......但是另一个正在编写类并希望像其他 IDisposable 通常使用的方式(在 using 块中)使用 IDisposable 的开发人员呢?
using(factory.CreateInstance())
{
....
}
对我来说看起来更清楚:
MyDisposable instance;
try
{
instance = factory.GetInstance();
}
finally
{
factory.Release(instance);
}
为了真正处理我的实例并使它们符合 GC 的条件,我需要引用 WindsorContainer 或使用公开发布方法的类型化工厂。这意味着使用 IDisposable 组件的唯一可接受的方法是使用类型化工厂。在我看来,这不好……如果有人将 IDisposable 接口添加到现有组件中怎么办? 每个需要注入组件的地方都需要改变。在我看来这真的很糟糕。 (当然,在非 DI 场景中,也需要更改为调用 Dispose...但是对于 Windsor,每个地方都需要更改为使用类型化工厂,这是一个更大的更改)。
好吧,公平地说,我可以使用自定义 ReleasePolicy 对吧?这个怎么样?
public class CustomComponentsReleasePolicy : AllComponentsReleasePolicy
{
public override void Track(object instance, Burden burden)
{
if (burden.Model.LifestyleType == LifestyleType.Pooled)
base.Track(instance, burden);
}
}
好的,太好了,我的 IDisposable Transient 组件现在将被 GC 处理。
如果我想使用 TypedFactory 以便我的类可以生成某个类型的许多实例,该怎么办?
public interface IMyFactory
{
MyDisposable GetInstance();
void Release(MyDisposable instance);
}
[Singleton]
public class TestClass
{
public TestClass(IMyFactory factory) { }
}
好吧,一方面,在工厂上调用 Release 对在 MyDisposable 上调用 Dispose() 没有任何作用,因为 MyDisposable 没有被跟踪......
我该如何克服这些困难?
谢谢。
I know this has been discussed ad nauseum...but I have an issue with the way Windsor is tracking Transient IDisposable objects.
I understand the benefits of letting Windsor manage my IDiposables...but I don't like it.
What happens if I want to wrap my component in a using block? The coder would make the assumption the resource would get cleaned up at the end of the using block, right? Wrong - Dispose would be called, but Windsor would hold onto the instance until explicitly released. This is all well and fine for me, since I know what I'm doing...but what about another developer who's coding a class and wants to use an IDisposable the way every other IDisposable is usually used - in a using block?
using(factory.CreateInstance())
{
....
}
looks much clearer to me than:
MyDisposable instance;
try
{
instance = factory.GetInstance();
}
finally
{
factory.Release(instance);
}
In order to truly dispose my instances and have them eligible for GC, I need to reference the WindsorContainer or use a typed factory that exposes a release method. That means the only acceptable way of using IDisposable components is to use a typed factory. This is not good, in my opinion...what if someone adds the IDisposable interface to an existing component? Every single place that expects the component to be injected will need to change. That's really bad in my opinion. (Granted, in a non DI scenario, it would need to change to call Dispose also...but with Windsor every place will need to change to use a typed factory, which is a much larger change).
Ok, fair enough, I can use a custom ReleasePolicy right? How about this?
public class CustomComponentsReleasePolicy : AllComponentsReleasePolicy
{
public override void Track(object instance, Burden burden)
{
if (burden.Model.LifestyleType == LifestyleType.Pooled)
base.Track(instance, burden);
}
}
Ok, great, my IDisposable Transient components will be GC'd now.
What if I want to use a TypedFactory so my class can produce many instances of a type?
public interface IMyFactory
{
MyDisposable GetInstance();
void Release(MyDisposable instance);
}
[Singleton]
public class TestClass
{
public TestClass(IMyFactory factory) { }
}
Ok, well, for one, calling Release on factory will do nothing to call Dispose() on MyDisposable, since MyDisposable isn't tracked....
How can I overcome these difficulties?
Thanks.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
首先,您如何知道与您未创建的对象相关的退役问题?您无法控制对象的创建,因为您没有自己创建它(工厂为您创建了此操作)。当您将ioc解析与消费者处置(调用.Dispose而不是factory.Release)结合起来时,您将引入这样的要求:您的对象知道它是如何创建的,但它并没有创建自己。考虑以下示例:
“组件”是您通过容器解析的东西,但您想自行处理
如上所示,退役可能很复杂,我简单地不知道如何自己优雅地处理这个问题,特别是当 Windsor 这样做时为我。如果您的代码库中充斥着服务定位器反模式(http:// blog.ploeh.dk/2010/02/03/ServiceLocatorisanAnti-Pattern/)我可以看到这如何成为一个问题(我不是说你的代码是),但是你真的有多少更大的问题。
嗯,using 语句是一种约定,如果省略它,则不会出现编译时错误,所以从我的角度来看,try/finally 与 release 只是另一个约定,尽管有点冗长。例如,您可以通过创建一个助手来缩短 try/finally ,例如:
我不明白这个说法。如何释放组件以及何时需要它是不同的问题,如果组件作为构造函数依赖项提供,则添加 IDisposable 不会改变任何内容。通过构造函数获取依赖项的类并未创建它,因此不负责释放它。
First of all, how do you know the decommision concerns associated with an object which you did not create? You do not have control over the creation of the object because you did not create it yourself (the factory did this for you). When you combine ioc resolving with consumer disposing (calling .Dispose instead of factory.Release) you are introducing the requirement that you object knows how it was created, yet it did not create itself. Consider the following example:
“Component” is something you resolve through the container, but you want to dispose of yourself
As shown above decommission can be complex and I simple don’t see how I can handle this gracefully myself, especially when Windsor does this for me. If your codebase is littered with the service-locator anti-pattern (http://blog.ploeh.dk/2010/02/03/ServiceLocatorisanAnti-Pattern/) I can see how this becomes an issue (I am not saying that you code is), but then you really how lot bigger problems.
Well the using statement is a convention, there no compile time error if you omit it, so from my point of view the try/finally with release is just another convention, although a bit more verbose. You could for example shorten the try/finally by creating a helper, such as:
I don’t understand this statement. How a component is released and when you need it are to different concerns, if a component is provided as a constructor dependency, adding IDisposable doesn’t change anything. The class which gets the dependency through the constructor did not create it and is therefore not responsible for releasing it.
作为背负者,您可以通过创建一个为您释放对象的拦截器来解决您提到的其他一些问题。我这样做是为了一个工作单元。拦截器如下所示:
我的注册代码如下所示:
代理挂钩只是表明我只想代理 IDiposable 接口方法。该类如下所示:
由于我正在使用我正在使用的钩子的重载,因此也需要注册:
As a piggy back, you can solve some of the other points you mentioned by creating an interceptor that releases your object for you. I do this for a unit of work concern. The interceptor looks like this:
My registration code looks like this:
The proxy hook is only there to say that I only want to proxy the IDiposable interface methods. That class looks like this:
Which also requires to be registered since I'm using the overload of hook that I'm using: