.net – 城堡温莎瞬态一次性用品

我知道这已经讨论过恶心…但我有一个问题,Windsor正在跟踪Transient IDisposable对象的方式.

我明白让温莎管理我的IDiposables的好处…但我不喜欢它.

如果我想将组件包装在一个使用块中会怎么样?编码器将假设资源在使用块的末尾被清理,对吧?错误 – 将被调用,但Windsor会持有该实例,直到明确释放.这对我来说都是好的,因为我知道我正在做什么…但是另一个开发人员编码一个类,并希望使用IDisposable通常使用每一个其他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瞬态组件将现在GC.

如果我想使用TypedFactory,那么我的类可以生成许多类型的实例呢?

public interface IMyFactory 
{
    MyDisposable GetInstance();
    void Release(MyDisposable instance);
}

[Singleton]
public class TestClass
{
    public TestClass(IMyFactory factory) { }
}

好的,一个,因为MyDisposable没有跟踪,所以在工厂调用Release将不会在MyDisposable上调用Dispose().

如何克服这些困难?

谢谢.

最佳答案
首先,你如何知道与没有创建的对象相关联的解决方案?您无法控制对象的创建,因为您没有自己创建它(工厂为您完成此操作).当您将ioc解析与消费者处理(调用.Dispose而不是factory.Release)组合时,您将引入对象知道如何创建的要求,但它并未创建自身.请考虑以下示例:

“组件”是您通过容器解决的问题,但您想要处理自己

public class Component : IDisposable
{
    private readonly IAmSomething _something;

    public Component(IAmSomething something)
    {
        _something = something;
    }

    public void Dispose()
    {
        // Problem 1: the component doesnt know that an implementation of IAmSomething might be disposable
        // Problem 2: the component did not create "something" so it does not have the right to dispose it
        // Problem 3: What if an implementation of "something" has a depenency on a disposable instance deep down in its object graph?

        // this is just bad..
        IDisposable disposable = _something as IDisposable;

        if (disposable != null)
            disposable.Dispose();

    }
}

public interface IAmSomething
{

}

public class SomethingA : IAmSomething
{

}

public class SomethingB : IAmSomething, IDisposable 
{
    public void Dispose()
    {
    }
}

如上图所示,退役可能很复杂,我简单看不出我如何处理这个优雅的自己,特别是当温莎为我做这件事时.如果您的代码库散布在服务定位器反模式(http://blog.ploeh.dk/2010/02/03/ServiceLocatorisanAnti-Pattern/)中,我可以看到这是如何成为一个问题(我不是说你的代码是),但是你真的有多大的问题.

06001

looks much clearer to me than: …

那么使用语句是一个约定,如果你省略它没有编译时错误,所以从我的角度来看,try / finally与release只是另一个约定,虽然有点更详细.你可以通过创建一个帮助器来缩短try / finally,例如:

[TestFixture]
public class SomeCastleTests
{
    [Test]
    public void Example()
    {
        var container = new WindsorContainer();

        // you would of course use a typed factory instead in real word

        using (var usage = new ComponentUsage<IAmSomething>(container.Resolve<IAmSomething>, container.Release))
        {
            // use..
            usage.Component
        }
    }
}

public class ComponentUsage<T> : IDisposable where T : class
{
    private Func<T> _create;
    private Action<T> _release;

    private T _instance;

    public ComponentUsage(Func<T> create, Action<T> release)
    {
        _create = create;
        _release = release;
    }

    public T Component
    {
        get
        {
            if (_instance == null)
                _instance = _create();

            return _instance;
        }
    }

    public void Dispose()
    {
        if (_instance != null)
        {
            _release(_instance);
            _instance = null;
        }
    }
}

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.

我不明白这个说法.组件如何被释放,当你需要它是不同的问题,如果一个组件作为构造函数依赖提供,添加IDisposable不会改变任何东西.通过构造函数获取依赖关系的类没有创建它,因此不负责释放它.

转载注明原文:.net – 城堡温莎瞬态一次性用品 - 代码日志