JD2022-TU1/main/tools/framework/JD.Kernel/Classes/SuspendableEvent.cs

133 lines
No EOL
3.2 KiB
C#

using System;
using System.Collections.Generic;
namespace JD.Kernel.Classes
{
/// <summary>
/// Event that triggers normally but can be suspended. In suspend mode, events are recorded.
/// </summary>
/// <typeparam name="TEventArgs">Eventargs of the final event.</typeparam>
public class SuspendableEvent<TEventArgs>
{
#region Variables
private readonly Scope m_suspend = new Scope();
private List<RecordedEvent> m_journal = new List<RecordedEvent>();
#endregion
#region Constructor
public SuspendableEvent()
{
m_suspend.EndScope += delegate
{
FlushJournal();
};
}
#endregion
#region Properties
/// <summary>
/// During the activity of the scope, events are recorded.
/// </summary>
public Scope Suspend
{
get { return m_suspend; }
}
#endregion
#region Methods
private void FlushJournal()
{
if (m_journal.Count > 0)
{
List<RecordedEvent> suspendedEvents = m_journal;
m_journal = new List<RecordedEvent>();
suspendedEvents.ForEach(RaiseImpl);
}
}
#endregion
#region Operators
public static SuspendableEvent<TEventArgs> operator +(SuspendableEvent<TEventArgs> @event, EventHandler<TEventArgs> handler)
{
SuspendableEvent<TEventArgs> result = @event ?? new SuspendableEvent<TEventArgs>();
result.Event += handler;
return result;
}
public static SuspendableEvent<TEventArgs> operator -(SuspendableEvent<TEventArgs> @event, EventHandler<TEventArgs> handler)
{
if (@event != null)
{
@event.Event -= handler;
if (@event.Event == null)
{
return null;
}
return @event;
}
return null;
}
/// <summary>
/// Triggers the event.
/// </summary>
internal void RaiseInternal(object sender, TEventArgs e)
{
if (!m_suspend.InScope)
{
RaiseImpl(sender, e);
}
else
{
m_journal.Add(new RecordedEvent(sender, e));
}
}
#endregion
#region Event
/// <summary>
/// The final triggered event.
/// </summary>
private event EventHandler<TEventArgs> Event;
private void RaiseImpl(object sender, TEventArgs e)
{
Event?.Invoke(sender, e);
}
private void RaiseImpl(RecordedEvent @event)
{
RaiseImpl(@event.Sender, @event.EventArgs);
}
#endregion
#region Nested Types
private struct RecordedEvent
{
public readonly object Sender;
public readonly TEventArgs EventArgs;
public RecordedEvent(object sender, TEventArgs eventArgs)
{
Sender = sender;
EventArgs = eventArgs;
}
}
#endregion
}
}