У меня есть следующее бизнес-правило: у меня есть лицензия, которую я получаю от другой программы, которая должна использоваться третьей программой. После того, как третья программа подтверждает, что она получила лицензию, я хочу записать ее в файл для целей документации. Если что-то пойдет не так (включая пользователя, закрывающего часть моего приложения, которая ожидает ответа), мне нужно записать лицензию обратно в программу, которая отправляет мне лицензию, чтобы сохранить ее там снова. Мне (в целях безопасности, как мне говорят) не разрешено просто сохранять лицензию (зашифрованную или нет) в файле и вызывать ее через день.
Основной случай, когда другое приложение ожидает подтверждения лицензиипрост:
public bool UseKey(Func<string, bool> func, string serviceTag)
{
Throw.IfNull(serviceTag, nameof(serviceTag));
Throw.IfNull(func, nameof(func)); //Check if null
if (func(_license)) //Programm acknowledged.
{
_keyUsed.OnNext(new UsedKey(serviceTag, _license)); //License was used. Therefore inform others that it can be written to file.
return true;
}
return false; //Didn't work. Inform caller.
}
Моя идея для случая, когда что-то пошло не так, была следующая: я реализую интерфейс IDisposable
, и в моем методе Dispose (bool) я отправлю правильное событие, информирующееобработчик, чтобы правильно написать обратно.
void Dispose(bool disposing)
{
if (!_disposed)
{
if (disposing)
{
if (!_keyWasUsed)
_keyNotUsed.OnNext(_license);
_keyUsed.Dispose();
_keyNotUsed.Dispose();
}
// TODO: free unmanaged resources (unmanaged objects) and override a finalizer below.
// TODO: set large fields to null.
_disposed = true;
}
}
Проблема, которую я вижу, имеет две стороны.
- Если клиент не вызывает метод
Dispose
, я бы не узнал, что что-то пошло не так. - Если я помещу вызов события в финализатор, я не смогуточно знаю, что я могу даже инициировать событие, потому что, возможно, мои ссылки уже очищены или поле лицензии уже собрано.
Поэтому мой вопрос (ы): Как я могу выпустить событие или некоторые другиесообщение (или Rx, или даже классические события, если это что-то облегчает) другому исполняемому коду из финализатора?
(или есть ли лучший подход, чем использование IDisposable
для такой работы, чтодает мне гарантию, что либо операция завершится успешно, либо я смогу выполнить откат (вроде транзакций sql)?)