У меня есть подкласс DbContext
public class MyContext : DbContext { }
и у меня есть абстракция IUnitOfWork
вокруг MyContext
, которая реализует 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 - правильный ответ):
- Ожидается, что каждый Decorator будет знать, является ли он временным или охваченным временем. Если декоратор временно, то он не должен вызывать
Dispose()
на украшенном экземпляре. Если это срок действия, он должен. - Каждый декоратор должен заботиться только об утилизации себя и никогда передавать вызов украшенному экземпляру. Контейнер будет управлять вызовом
Dispose()
для каждого объекта в цепочке вызовов в соответствующее время. Объект должен толькоDispose()
экземпляров, которые он инкапсулирует и украшает, не является инкапсуляцией.