0

https://github.com/int6/CoiniumServ/blob/develop/src/CoiniumServ/Pools/Pool.cs

这是我的泳池课。当我处理课程时,我想要那个。所有依赖项都应该停止工作并自行处理。

我尝试对所有依赖项实施 idisposable 来处理,但它不起作用。

我还实现了一个线程以在线程中运行函数并通过线程中止将其销毁。那也行不通。

有没有其他方法可以做到这一点?

4

1 回答 1

1

组件不应释放任何注入的依赖项。主要原因是:

  1. 该组件没有创建它们,因此不知道是否应该处理这些依赖项。
  2. 消费者甚至不应该意识到依赖项是一次性的。

组件依赖于寿命更长的服务是很常见的。如果消费组件处理该依赖项,则应用程序将中断,因为该依赖项在配置为使用时无法再使用。这是一个简单的例子:

// Singleton
private static readonly IRepository<User> repository = new UserRepository();

public IController CreateController(Type controllerType) {
    if (controllerType == typeof(UserController)) {
        return new UserController(repository);
    }

    // ...
}

这个例子包含一个单例UserRepository和一个瞬态UserController。对于每个请求,UserController都会创建一个新请求(想象一下 ASP.NET MVC 应用程序,这将开始有意义)。如果UserController将处置UserRepository,则下一个请求将获得一个UserController取决于已处置的UserRepository。这显然会很糟糕。

但除此之外,IRepository<T>应该实施。实现意味着抽象正在泄漏实现细节,因此违反了依赖倒置原则,该原则指出:IDisposableIDisposable

抽象不应该依赖于细节。细节应该取决于抽象。

仅当您绝对 100% 确定您将要进行的该抽象的所有实现都需要自行处理时,在抽象上实现IDisposable才有意义。但这几乎从来没有发生过。想象一下在你的单元测试中有一个实现。这种虚假的实现永远不需要处置,因此并非所有实现都需要处置,并且您正在泄漏实现细节。FakeRepository<T>

这仅仅意味着您应该将IDisposable接口移至实现。例如:

public interface IRepository<T> { }

public class UserRepository : IRepository<User>, IDisposable { }

请注意,将IDisposable接口放在抽象上,虽然并非所有消费者都应该调用Dispose也意味着您违反了接口隔离原则,该原则指出:

不应强迫任何客户依赖它不使用的方法。

这样做的好处是,使用组件(例如UserController)不可能意外调用Dispose()并因此可能破坏系统。

另一个优点是,由于组件不需要释放它们的依赖关系,因此对于大多数组件来说,不会留下任何释放逻辑,从而使系统更加简单和易于维护。

于 2015-07-04T12:39:16.227 回答