我使用ASP.NET Core构建了一个API服务。就像任何其他API一样,这个API必须从数据库中检索一些数据,应用一些业务逻辑,然后将数据发送回客户端。
首先,我有使用Entity Framework.Core搭建的EmployeeDataContext类。此类派生自Microsoft.EntityFrameworkCore.DbContext,如下所示。
public partial class EmployeeDataContext : DataContext
{
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
......
}
}
此数据上下文类在数据提供程序类中使用如下。
public class EmployeeDataProvider : IEmployeeDataProvider, IDisposable
{
private EmployeeDataContext dataContext;
public EmployeeDataProvider(EmployeeDataContext context)
{
this.dataContext = context;
}
// Various CRUD methods
// Dispose
public void Dispose()
{
if ( this.dataContext != null )
{
this.dataContext.Dispose();
}
}
}
服务层保存对数据提供者的引用,如下所示。
public class EmployeeService : IEmployeeService
{
private IEmployeeDataProvider dataProvider;
public EmployeeService(IEmployeeDataProvider dataProvider)
{
DataProvider = dataProvider;
}
// Add/Delete/Update Employee related calls
}
所有依赖项都在Startup类中注入,如下所示。
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddScoped<IEmployeeDataProvider, EmployeeDataProvider>();
services.AddScoped<IEmployeeService, EmployeeService>();
}
}
根据微软doc
容器将为它创建的IDisposable类型调用Dispose。
这意味着EmployeeDataProvider.Dispose()方法将在请求生命周期结束时由容器调用。
我的问题是如何为EmployeeDataProvider类实现IDisposable。 link提供了针对各种场景实现IDisposable的最佳实践,这些场景可能还需要您实现Disposable(bool)。但是,对于这种情况,我不确定是否 所有需要的东西和我目前(简单)的Dispose实现是足够好的,因为(因为这里没有涉及通过终结器调用)。我的理解和IDisposable看起来对这种情况是否正确?
答案 0 :(得分:4)
在您的班级为IDisposable
的情况下,实施sealed
是微不足道的:
public sealed class Foo : IDisposable {
private readonly FileStream stream;
public Foo() {
this.stream = new FileStream( ... );
}
public void Dispose() {
this.stream.Dispose();
}
}
如果您的类将被子类化,则只需要protected virtual void Dispose(Boolean disposing)
方法和IDisposable
的推荐实现。
这在FxCop规则CA1063&#34;正确实施IDisposable&#34;:https://msdn.microsoft.com/en-us/library/ms244737.aspx
的文档中有所描述
- Dispose()不公开,密封或命名为Dispose。
- Dispose(bool)不受保护,虚拟或未密封。
- 在未密封的类型中,Dispose()必须调用Dispose(true)。
- 对于未密封的类型,Finalize实现不会调用Dispose(bool)或case case finalizer中的任何一个或两者。
[...]
如何修复违规行为
[...] 确保将
$className
声明为公开并密封。
另一个提示:如果您的字段仅在类型初始值设定项或构造函数中分配 - 并且永远不应分配空值 - 那么您应该使用readonly
修饰符(或使用只读自动 - 属性 - 具有readonly
支持字段)以及您不需要执行null
的方式 - 检查Dispose
方法。
请注意,Dispose()
方法通常是幂等的:
https://msdn.microsoft.com/en-us/library/fs2xkftw.aspx
为了确保始终适当地清理资源,Dispose方法应该可以多次调用,而不会抛出异常。
从历史上看,.NET 1.x和2.x中有一些类如果它们被Disposed两次就会抛出ObjectDisposesException
,但我个人观察到自升级到非幂等行为。 NET 4.x - 但是,一些写得不好的第三方库和组件可能会错误地实现它。