https://github.com/int6/CoiniumServ/blob/develop/src/CoiniumServ/Pools/Pool.cs
这是我的泳池班。当我处理课程时我想要那个。所有依赖都应该停止工作并自行处理。
我尝试并实现了所有依赖关系的idisposable,但它不起作用。
我还实现了一个线程来运行线程中的函数并使用线程中止来销毁它。那也行不通。
有没有其他方法可以做到这一点?
答案 0 :(得分:1)
组件应该不处理任何注入的依赖项。主要原因是:
组件依赖于具有较长生活方式的服务是很常见的。如果使用组件处理该依赖项,则应用程序将中断,因为在将其配置为使用时,不能再使用该依赖项。这是一个简单的例子:
// 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>
应该不实施IDisposable
。实现IDisposable
意味着抽象漏掉了实现细节,因此违反了Dependency Inversion Principle,其中指出:
抽象不应该依赖于细节。细节应该取决于 抽象。
在抽象上实现IDisposable
只有在绝对100%确定所有实现的抽象时才有意义,这些抽象是你需要自己处理的。但事实并非如此。试想在单元测试中实现FakeRepository<T>
。这样的虚假实现永远不需要处理,因此并非所有实现都需要处理,而且您正在泄漏实现细节。
这只是意味着您应该将IDisposable
接口移动到实现。例如:
public interface IRepository<T> { }
public class UserRepository : IRepository<User>, IDisposable { }
请注意,在抽象上使用IDisposable
接口,而不是所有消费者都应该调用Dispose
也意味着您违反了Interface Segregation Principle声明:
不应该强迫任何客户端依赖它不使用的方法。
这样做的好处是消费组件(例如UserController
)不可能意外地调用Dispose()
并且可能会破坏系统。
另一个优点是,由于组件不需要处理它们的依赖关系,因此对于大多数组件而言,将不会留下任何处理逻辑,从而使系统更加简单和易于维护。