【发布时间】:2013-07-30 09:55:45
【问题描述】:
我有一个DbContext 的子类
public class MyContext : DbContext { }
我在MyContext 周围有一个IUnitOfWork 抽象,它实现了IDisposable,以确保在适当的时间处理MyContext 等引用
public interface IUnitOfWork : IDisposable { }
public class UnitOfWork : IUnitOfWork
{
private readonly MyContext _context;
public UnitOfWork()
{
_context = new MyContext();
}
~UnitOfWork()
{
Dispose(false);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
private bool _disposed;
protected virtual void Dispose(bool disposing)
{
if (_disposed) return;
if (disposing)
{
if (_context != null) _context.Dispose();
}
_disposed = true;
}
}
我的UnitOfWork 注册了每个(网络)请求的生命周期范围。我有IUnitOfWork 的装饰器可以注册为瞬态或生命周期范围,我的问题是他们应该如何实现IDisposable - 特别是他们应该还是不应该将调用传递给Dispose()。
public class UnitOfWorkDecorator : IUnitOfWork
{
private readonly IUnitOfWork _decorated;
public UnitOfWorkDecorator(IUnitOfWork decorated)
{
_decorated = decorated;
}
public void Dispose()
{
//do we pass on the call?
_decorated.Dispose();
}
}
我看到了 2 个选项(我猜选项 2 是正确答案):
- 希望每个装饰器都知道它是瞬态的还是生命周期的。如果装饰器是瞬态的,那么它不应该在被装饰的实例上调用
Dispose()。如果它是生命周期范围的,它应该。 - 每个装饰器应该只关心自己的处理,并且应该从不将调用传递给被装饰的实例。容器将在适当的时候为调用链中的每个对象管理对
Dispose()的调用。一个对象应该只封装Dispose()个实例,而装饰不是封装。
【问题讨论】:
-
很好的问题。此外,您应该在 Dispose 方法中将 _context 变量设置为 null,就在您处理完该上下文之后。
-
我同意@Maarten:一个非常棒且非常有趣的问题。
标签: c# decorator ioc-container simple-injector