using Quasar.Common.Networking;
using System;
using System.Threading;
namespace Quasar.Common.Messages
{
///
/// Provides a MessageProcessor implementation that provides progress report callbacks.
///
/// Specifies the type of the progress report value.
///
/// Any event handlers registered with the event are invoked through a
/// instance chosen when the instance is constructed.
///
public abstract class MessageProcessorBase : IMessageProcessor, IProgress
{
///
/// The synchronization context chosen upon construction.
///
protected readonly SynchronizationContext SynchronizationContext;
///
/// A cached delegate used to post invocation to the synchronization context.
///
private readonly SendOrPostCallback _invokeReportProgressHandlers;
///
/// Represents the method that will handle progress updates.
///
/// The message processor which updated the progress.
/// The new progress.
public delegate void ReportProgressEventHandler(object sender, T value);
///
/// Raised for each reported progress value.
///
///
/// Handlers registered with this event will be invoked on the
/// chosen when the instance was constructed.
///
public event ReportProgressEventHandler ProgressChanged;
///
/// Reports a progress change.
///
/// The value of the updated progress.
protected virtual void OnReport(T value)
{
// If there's no handler, don't bother going through the sync context.
// Inside the callback, we'll need to check again, in case
// an event handler is removed between now and then.
var handler = ProgressChanged;
if (handler != null)
{
SynchronizationContext.Post(_invokeReportProgressHandlers, value);
}
}
///
/// Initializes the
///
///
/// If this value is false, the progress callbacks will be invoked on the ThreadPool.
/// Otherwise the current SynchronizationContext will be used.
///
protected MessageProcessorBase(bool useCurrentContext)
{
_invokeReportProgressHandlers = InvokeReportProgressHandlers;
SynchronizationContext = useCurrentContext ? SynchronizationContext.Current : ProgressStatics.DefaultContext;
}
///
/// Invokes the progress event callbacks.
///
/// The progress value.
private void InvokeReportProgressHandlers(object state)
{
var handler = ProgressChanged;
handler?.Invoke(this, (T)state);
}
///
public abstract bool CanExecute(IMessage message);
///
public abstract bool CanExecuteFrom(ISender sender);
///
public abstract void Execute(ISender sender, IMessage message);
void IProgress.Report(T value) => OnReport(value);
}
///
/// Holds static values for .
///
///
/// This avoids one static instance per type T.
///
internal static class ProgressStatics
{
///
/// A default synchronization context that targets the .
///
internal static readonly SynchronizationContext DefaultContext = new SynchronizationContext();
}
}