Ответ 1
Только код, выполняющий изменения, может знать, когда завершена его партия изменений.
То, что я сделал с моими аналогичными классами, заключается в предоставлении методов SuspendNotifications()
и ResumeNotifications()
, которые вызываются очевидным образом (т.е. вызывают приостановку перед тем, как сделать кучу изменений, при необходимости вызовите резюме).
Они внутренне поддерживают счетчик, который увеличивается в SuspendNotifications() и уменьшается с помощью ResumeNotifications(), и если декремент приводит к нулю, выдается уведомление. Я сделал это так, потому что иногда мне нужно было модифицировать некоторые свойства, а затем вызвать другой метод, который изменил еще несколько, и который сам будет вызывать suspend/resume.
(Если резюме вызвано слишком много раз, я выбрал исключение.)
Если изменено несколько свойств, окончательное уведомление не называет измененное свойство (поскольку их несколько). Я полагаю, вы могли бы накапливать список измененных свойств и выпускать это как часть уведомления, но это не очень полезно.
Также обратите внимание, что безопасность потока может быть или не быть проблемой для вас. Возможно, вам придется использовать блокировку и/или Interlocked.Increment()
и т.д.
Другое дело, что вам, конечно, нужно попробовать/поймать свои звонки, чтобы приостановить/возобновить в случае исключения. Вы можете избежать этого, написав класс-оболочку, который реализует IDisposable и вызывает возобновление в своем Dispose.
Код может выглядеть так:
public void DoStuff()
{
try
{
_entity.SuspendNotifications();
setProperties();
}
finally
{
_entity.ResumeNotifications();
}
}
private setProperties()
{
_entity.ID = 123454;
_entity.Name = "Name";
_entity.Description = "Desc";
}
[EDIT]
Если бы вы представили интерфейс, скажем ISuspendableNotifications
, вы можете написать класс оболочки IDisposable
для упрощения.
Пример ниже иллюстрирует концепцию; Использование NotificationSuspender
упрощает (фактически удаляет) логику try/catch.
Обратите внимание, что class Entity
, конечно, фактически не реализует приостановку/возобновление или не обеспечивает обработку ошибок; который оставил в качестве пресловутого упражнения для читателя.:)
using System;
namespace Demo
{
public interface ISuspendableNotifications
{
void SuspendNotifications();
void ResumeNotifications();
}
public sealed class NotificationSuspender: IDisposable
{
public NotificationSuspender(ISuspendableNotifications suspendableNotifications)
{
_suspendableNotifications = suspendableNotifications;
_suspendableNotifications.SuspendNotifications();
}
public void Dispose()
{
_suspendableNotifications.ResumeNotifications();
}
private readonly ISuspendableNotifications _suspendableNotifications;
}
public sealed class Entity: ISuspendableNotifications
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public void SuspendNotifications() {}
public void ResumeNotifications() {}
}
public static class Program
{
public static void Main(string[] args)
{
Entity entity = new Entity();
using (new NotificationSuspender(entity))
{
entity.Id = 123454;
entity.Name = "Name";
entity.Description = "Desc";
}
}
}
}