Основанный на this post, я создал мост между компонентами для форм Windows и IDisposable объектов. Это в значительной степени выглядит следующим образом:Почему Dispose вызывается, если мой объект никогда не был создан?
namespace MyApp
{
public class Disposer: Component
{
private readonly Action<bool> _dispose;
public Disposer(Action<bool> disposeCallback)
{
if (disposeCallback == null)
throw new ArgumentNullException(nameof(disposeCallback));
this._dispose = disposeCallback;
}
protected override void Dispose(bool disposing)
{
this._dispose(disposing);
base.Dispose(disposing);
}
}
}
Пока все хорошо. Затем я создал модульные тесты, в том числе один для конкретной проверки в аргументе конструктора.
[TestMethod]
[ExpectedException(typeof(ArgumentNullException))]
public void Disposer_ShouldNotAllowNullActions()
{
new Disposer(null);
}
Вот улов: не только мой тест терпит неудачу, но он фактически прерван. Сбой самой тестовой платформы (тестовый бегун ReSharper). Покопавшись в моем средстве просмотра событий Windows, я мог видеть, что метод Dispose() вызывается, и поскольку this._dispose
по существу является нулевым на данный момент, он терпит неудачу с .
Я установил это с предоставлением пустой лямбды в качестве значения по умолчанию.
Но если конструктор выбрасывает исключение (что я его подтвердил), почему вообще вызван метод Dispose
?
Что делать, если конструктор уже приобрел некоторые доступные ресурсы до того, как будет выброшено исключение? Эти ресурсы по-прежнему необходимо освободить. –
В чем заключается цель получения делегата, вызываемого при удалении объекта? Какой прецедент? –
@DStanley IDisposable может быть создан в форме, но вы захотите избавиться от них, когда форма фактически удалена (не закрыта). Dispose уже переопределяется в сгенерированном виде кодом, поэтому способ подключиться к нему - это зарегистрировать компонент. (Мне не понравилось перемещение сгенерированного кода.) – Alpha