diff --git a/src/Build/Logging/DistributedLoggers/ConfigurableForwardingLogger.cs b/src/Build/Logging/DistributedLoggers/ConfigurableForwardingLogger.cs index 277352b56a0..fc69e41d38d 100644 --- a/src/Build/Logging/DistributedLoggers/ConfigurableForwardingLogger.cs +++ b/src/Build/Logging/DistributedLoggers/ConfigurableForwardingLogger.cs @@ -1,14 +1,9 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System; -using System.Collections.Generic; - using Microsoft.Build.Framework; using Microsoft.Build.Shared; -#nullable disable - namespace Microsoft.Build.Logging { /// @@ -22,9 +17,7 @@ public class ConfigurableForwardingLogger : IForwardingLogger /// Default constructor. /// public ConfigurableForwardingLogger() - { - InitializeForwardingTable(); - } + { } #endregion #region Properties @@ -44,7 +37,7 @@ public LoggerVerbosity Verbosity /// and warnings summary at the end of a build. /// /// null - public string Parameters + public string? Parameters { get { return _loggerParameters; } set { _loggerParameters = value; } @@ -54,7 +47,7 @@ public string Parameters /// This property is set by the build engine to allow a node loggers to forward messages to the /// central logger /// - public IEventRedirector BuildEventRedirector + public IEventRedirector? BuildEventRedirector { get { return _buildEventRedirector; } set { _buildEventRedirector = value; } @@ -72,35 +65,10 @@ public int NodeId #region Methods - /// - /// Initialize the Forwarding Table with the default values - /// - private void InitializeForwardingTable() - { - _forwardingTable = new Dictionary(16, StringComparer.OrdinalIgnoreCase); - _forwardingTable[BuildStartedEventDescription] = 0; - _forwardingTable[BuildFinishedEventDescription] = 0; - _forwardingTable[ProjectStartedEventDescription] = 0; - _forwardingTable[ProjectFinishedEventDescription] = 0; - _forwardingTable[ProjectEvaluationEventDescription] = 0; - _forwardingTable[TargetStartedEventDescription] = 0; - _forwardingTable[TargetFinishedEventDescription] = 0; - _forwardingTable[TaskStartedEventDescription] = 0; - _forwardingTable[TaskFinishedEventDescription] = 0; - _forwardingTable[ErrorEventDescription] = 0; - _forwardingTable[WarningEventDescription] = 0; - _forwardingTable[HighMessageEventDescription] = 0; - _forwardingTable[NormalMessageEventDescription] = 0; - _forwardingTable[LowMessageEventDescription] = 0; - _forwardingTable[CustomEventDescription] = 0; - _forwardingTable[CommandLineDescription] = 0; - _forwardingSetFromParameters = false; - } - /// /// Parses out the logger parameters from the Parameters string. /// - private void ParseParameters() + private void ParseParameters(IEventSource eventSource) { if (_loggerParameters != null) { @@ -109,7 +77,7 @@ private void ParseParameters() { if (parameterComponents[param].Length > 0) { - ApplyParameter(parameterComponents[param]); + ApplyParameter(eventSource, parameterComponents[param]); } } // Setting events to forward on the commandline will override the verbosity and other switches such as @@ -125,8 +93,8 @@ private void ParseParameters() // We can't know whether the project items needed to find ForwardProjectContextDescription // will be set on ProjectStarted or ProjectEvaluationFinished because we don't know // all of the other loggers that will be attached. So turn both on. - _forwardingTable[ProjectStartedEventDescription] = 1; - _forwardingTable[ProjectEvaluationEventDescription] = 1; + eventSource.HandleStatusEventRaised(BuildStatusHandler); + eventSource.HandleProjectStarted(ForwardEvent); } } } @@ -135,39 +103,93 @@ private void ParseParameters() /// Logger parameters can be used to enable and disable specific event types. /// Otherwise, the verbosity is used to choose which events to forward. /// - private void ApplyParameter(string parameterName) + private void ApplyParameter(IEventSource eventSource, string parameterName) { ErrorUtilities.VerifyThrowArgumentNull(parameterName, nameof(parameterName)); - if (_forwardingTable.ContainsKey(parameterName)) - { - _forwardingSetFromParameters = true; - _forwardingTable[parameterName] = 1; - } - else if (String.Equals(parameterName, ProjectEvaluationStartedEventDescription, StringComparison.OrdinalIgnoreCase) || - String.Equals(parameterName, ProjectEvaluationFinishedEventDescription, StringComparison.OrdinalIgnoreCase)) + bool isEventForwardingParameter = true; + + // Careful - we need to brace before double specified parameters - hence the unsubscriptions before subscriptions + switch (parameterName.ToUpperInvariant()) + { + case BuildStartedEventDescription: + eventSource.HandleBuildStarted(ForwardEvent); + break; + case BuildFinishedEventDescription: + eventSource.HandleBuildFinished(ForwardEvent); + break; + case ProjectStartedEventDescription: + eventSource.HandleProjectStarted(ForwardEvent); + break; + case ProjectFinishedEventDescription: + eventSource.HandleProjectFinished(ForwardEvent); + break; + case TargetStartedEventDescription: + eventSource.HandleTargetStarted(ForwardEvent); + break; + case TargetFinishedEventDescription: + eventSource.HandleTargetFinished(ForwardEvent); + break; + case TaskStartedEventDescription: + eventSource.HandleTaskStarted(ForwardEvent); + break; + case TaskFinishedEventDescription: + eventSource.HandleTaskFinished(ForwardEvent); + break; + case ErrorEventDescription: + eventSource.HandleErrorRaised(ForwardEvent); + break; + case WarningEventDescription: + eventSource.HandleWarningRaised(ForwardEvent); + break; + case CustomEventDescription: + eventSource.HandleCustomEventRaised(ForwardEvent); + break; + case HighMessageEventDescription: + eventSource.HandleMessageRaised(MessageHandler); + _forwardHighImportanceMessages = true; + break; + case NormalMessageEventDescription: + eventSource.HandleMessageRaised(MessageHandler); + _forwardNormalImportanceMessages = true; + break; + case LowMessageEventDescription: + eventSource.HandleMessageRaised(MessageHandler); + _forwardLowImportanceMessages = true; + break; + case CommandLineDescription: + eventSource.HandleMessageRaised(MessageHandler); + _forwardTaskCommandLine = true; + break; + case ProjectEvaluationStartedEventDescription: + case ProjectEvaluationFinishedEventDescription: + case ProjectEvaluationEventDescription: + eventSource.HandleStatusEventRaised(BuildStatusHandler); + break; + case PerformanceSummaryDescription: + _showPerfSummary = true; + isEventForwardingParameter = false; + break; + case NoSummaryDescription: + _showSummary = false; + isEventForwardingParameter = false; + break; + case ShowCommandLineDescription: + _showCommandLine = true; + isEventForwardingParameter = false; + break; + case ForwardProjectContextDescription: + _forwardProjectContext = true; + isEventForwardingParameter = false; + break; + default: + isEventForwardingParameter = false; + break; + } + + if (isEventForwardingParameter) { _forwardingSetFromParameters = true; - _forwardingTable[ProjectEvaluationEventDescription] = 1; - } - - // If any of the following parameters are set, we will make sure we forward the events - // necessary for the central logger to emit the requested information - if (String.Equals(parameterName, PerformanceSummaryDescription, StringComparison.OrdinalIgnoreCase)) - { - _showPerfSummary = true; - } - else if (String.Equals(parameterName, NoSummaryDescription, StringComparison.OrdinalIgnoreCase)) - { - _showSummary = false; - } - else if (String.Equals(parameterName, ShowCommandLineDescription, StringComparison.OrdinalIgnoreCase)) - { - _showCommandLine = true; - } - else if (string.Equals(parameterName, ForwardProjectContextDescription, StringComparison.OrdinalIgnoreCase)) - { - _forwardProjectContext = true; } } @@ -178,28 +200,14 @@ public virtual void Initialize(IEventSource eventSource) { ErrorUtilities.VerifyThrowArgumentNull(eventSource, nameof(eventSource)); - ParseParameters(); + ParseParameters(eventSource); ResetLoggerState(); if (!_forwardingSetFromParameters) { - SetForwardingBasedOnVerbosity(); + SetForwardingBasedOnVerbosity(eventSource); } - - eventSource.BuildStarted += BuildStartedHandler; - eventSource.BuildFinished += BuildFinishedHandler; - eventSource.ProjectStarted += ProjectStartedHandler; - eventSource.ProjectFinished += ProjectFinishedHandler; - eventSource.TargetStarted += TargetStartedHandler; - eventSource.TargetFinished += TargetFinishedHandler; - eventSource.TaskStarted += TaskStartedHandler; - eventSource.TaskFinished += TaskFinishedHandler; - eventSource.ErrorRaised += ErrorHandler; - eventSource.WarningRaised += WarningHandler; - eventSource.MessageRaised += MessageHandler; - eventSource.CustomEventRaised += CustomEventHandler; - eventSource.StatusEventRaised += BuildStatusHandler; } /// @@ -210,69 +218,74 @@ public void Initialize(IEventSource eventSource, int nodeCount) Initialize(eventSource); } - private void SetForwardingBasedOnVerbosity() + private void SetForwardingBasedOnVerbosity(IEventSource eventSource) { - _forwardingTable[BuildStartedEventDescription] = 1; - _forwardingTable[BuildFinishedEventDescription] = 1; + eventSource.HandleBuildStarted(ForwardEvent); + eventSource.HandleBuildFinished(ForwardEvent); if (IsVerbosityAtLeast(LoggerVerbosity.Quiet)) { - _forwardingTable[ErrorEventDescription] = 1; - _forwardingTable[WarningEventDescription] = 1; + eventSource.HandleErrorRaised(ForwardEvent); + eventSource.HandleWarningRaised(ForwardEvent); } if (IsVerbosityAtLeast(LoggerVerbosity.Minimal)) { - _forwardingTable[HighMessageEventDescription] = 1; + eventSource.HandleMessageRaised(MessageHandler); + _forwardHighImportanceMessages = true; } if (IsVerbosityAtLeast(LoggerVerbosity.Normal)) { - _forwardingTable[NormalMessageEventDescription] = 1; - _forwardingTable[ProjectStartedEventDescription] = 1; - _forwardingTable[ProjectFinishedEventDescription] = 1; - _forwardingTable[TargetStartedEventDescription] = 1; - _forwardingTable[TargetFinishedEventDescription] = 1; - _forwardingTable[CommandLineDescription] = 1; + // MessageHandler already subscribed + _forwardNormalImportanceMessages = true; + _forwardTaskCommandLine = true; + + eventSource.HandleProjectStarted(ForwardEvent); + eventSource.HandleProjectFinished(ForwardEvent); + eventSource.HandleTargetStarted(ForwardEvent); + eventSource.HandleTargetFinished(ForwardEvent); } if (IsVerbosityAtLeast(LoggerVerbosity.Detailed)) { - _forwardingTable[TargetStartedEventDescription] = 1; - _forwardingTable[TargetFinishedEventDescription] = 1; - _forwardingTable[TaskStartedEventDescription] = 1; - _forwardingTable[TaskFinishedEventDescription] = 1; - _forwardingTable[LowMessageEventDescription] = 1; + eventSource.HandleTaskStarted(ForwardEvent); + eventSource.HandleTaskFinished(ForwardEvent); + + // MessageHandler already subscribed + _forwardLowImportanceMessages = true; } if (IsVerbosityAtLeast(LoggerVerbosity.Diagnostic)) { - _forwardingTable[CustomEventDescription] = 1; - _forwardingTable[ProjectEvaluationEventDescription] = 1; + eventSource.HandleCustomEventRaised(ForwardEvent); + eventSource.HandleStatusEventRaised(BuildStatusHandler); } if (_showSummary) { - _forwardingTable[ErrorEventDescription] = 1; - _forwardingTable[WarningEventDescription] = 1; + eventSource.HandleErrorRaised(ForwardEvent); + eventSource.HandleWarningRaised(ForwardEvent); } if (_showPerfSummary) { - _forwardingTable[TargetStartedEventDescription] = 1; - _forwardingTable[TargetFinishedEventDescription] = 1; - _forwardingTable[TaskStartedEventDescription] = 1; - _forwardingTable[TaskFinishedEventDescription] = 1; - _forwardingTable[TargetStartedEventDescription] = 1; - _forwardingTable[TargetFinishedEventDescription] = 1; - _forwardingTable[ProjectStartedEventDescription] = 1; - _forwardingTable[ProjectFinishedEventDescription] = 1; - _forwardingTable[ProjectEvaluationEventDescription] = 1; + eventSource.HandleTaskStarted(ForwardEvent); + eventSource.HandleTaskFinished(ForwardEvent); + eventSource.HandleTargetStarted(ForwardEvent); + eventSource.HandleTargetFinished(ForwardEvent); + eventSource.HandleProjectStarted(ForwardEvent); + eventSource.HandleProjectFinished(ForwardEvent); + eventSource.HandleStatusEventRaised(BuildStatusHandler); } if (_showCommandLine) { - _forwardingTable[CommandLineDescription] = 1; + // Prevent double subscribe + eventSource.MessageRaised -= MessageHandler; + eventSource.MessageRaised += MessageHandler; + + _forwardTaskCommandLine = true; } } @@ -285,20 +298,17 @@ private void SetForwardingBasedOnVerbosity() /// internal MessageImportance GetMinimumMessageImportance() { - if (_forwardingTable[LowMessageEventDescription] == 1) + return _verbosity switch { - return MessageImportance.Low; - } - if (_forwardingTable[NormalMessageEventDescription] == 1) - { - return MessageImportance.Normal; - } - if (_forwardingTable[HighMessageEventDescription] == 1) - { - return MessageImportance.High; - } - // The logger does not log messages of any importance. - return MessageImportance.High - 1; + LoggerVerbosity.Minimal => MessageImportance.High, + LoggerVerbosity.Normal => MessageImportance.Normal, + LoggerVerbosity.Detailed => MessageImportance.Low, + LoggerVerbosity.Diagnostic => MessageImportance.Low, + + // The logger does not log messages of any importance. + LoggerVerbosity.Quiet => MessageImportance.High - 1, + _ => MessageImportance.High - 1, + }; } /// @@ -319,157 +329,35 @@ public virtual void Shutdown() } /// - /// Handler for build started events + /// Handler for build events /// /// sender (should be null) /// event arguments - private void BuildStartedHandler(object sender, BuildStartedEventArgs e) + private void ForwardEvent(object sender, BuildEventArgs e) { - // This is false by default - if (_forwardingTable[BuildStartedEventDescription] == 1) - { - ForwardToCentralLogger(e); - } + ForwardToCentralLogger(e); } - /// - /// Handler for build finished events - /// - /// sender (should be null) - /// event arguments - private void BuildFinishedHandler(object sender, BuildFinishedEventArgs e) - { - // This is false by default - if (_forwardingTable[BuildFinishedEventDescription] == 1) - { - ForwardToCentralLogger(e); - } - ResetLoggerState(); - } - - /// - /// Handler for project started events - /// - /// sender (should be null) - /// event arguments - private void ProjectStartedHandler(object sender, ProjectStartedEventArgs e) - { - if (_forwardingTable[ProjectStartedEventDescription] == 1) - { - ForwardToCentralLogger(e); - } - } - - /// - /// Handler for project finished events - /// - /// sender (should be null) - /// event arguments - private void ProjectFinishedHandler(object sender, ProjectFinishedEventArgs e) - { - if (_forwardingTable[ProjectFinishedEventDescription] == 1) - { - ForwardToCentralLogger(e); - } - } - - /// - /// Handler for target started events - /// - /// sender (should be null) - /// event arguments - private void TargetStartedHandler(object sender, TargetStartedEventArgs e) - { - if (_forwardingTable[TargetStartedEventDescription] == 1) - { - ForwardToCentralLogger(e); - } - } - - /// - /// Handler for target finished events - /// - /// sender (should be null) - /// event arguments - private void TargetFinishedHandler(object sender, TargetFinishedEventArgs e) - { - if (_forwardingTable[TargetFinishedEventDescription] == 1) - { - ForwardToCentralLogger(e); - } - } - - /// - /// Handler for task started events - /// - /// sender (should be null) - /// event arguments - private void TaskStartedHandler(object sender, TaskStartedEventArgs e) + private void BuildStatusHandler(object sender, BuildStatusEventArgs e) { - if (_forwardingTable[TaskStartedEventDescription] == 1) + if (e is ProjectEvaluationStartedEventArgs || e is ProjectEvaluationFinishedEventArgs) { ForwardToCentralLogger(e); } } /// - /// Handler for task finished events + /// Tailored handler for BuildMessageEventArgs - fine tunes forwarding of messages. /// /// sender (should be null) /// event arguments - private void TaskFinishedHandler(object sender, TaskFinishedEventArgs e) - { - if (_forwardingTable[TaskFinishedEventDescription] == 1) - { - ForwardToCentralLogger(e); - } - } - - /// - /// Prints an error event - /// - private void ErrorHandler(object sender, BuildErrorEventArgs e) - { - if (_forwardingTable[ErrorEventDescription] == 1) - { - ForwardToCentralLogger(e); - } - } - - /// - /// Prints a warning event - /// - private void WarningHandler(object sender, BuildWarningEventArgs e) - { - if (_forwardingTable[WarningEventDescription] == 1) - { - ForwardToCentralLogger(e); - } - } - - /// - /// Prints a message event - /// private void MessageHandler(object sender, BuildMessageEventArgs e) { - bool forwardEvent = false; - - if (_forwardingTable[LowMessageEventDescription] == 1 && e.Importance == MessageImportance.Low) - { - forwardEvent = true; - } - else if (_forwardingTable[NormalMessageEventDescription] == 1 && e.Importance == MessageImportance.Normal) - { - forwardEvent = true; - } - else if (_forwardingTable[HighMessageEventDescription] == 1 && e.Importance == MessageImportance.High) - { - forwardEvent = true; - } - else if (_forwardingTable[CommandLineDescription] == 1 && e is TaskCommandLineEventArgs) - { - forwardEvent = true; - } + bool forwardEvent = + (_forwardLowImportanceMessages && e.Importance == MessageImportance.Low) || + (_forwardNormalImportanceMessages && e.Importance == MessageImportance.Normal) || + (_forwardHighImportanceMessages && e.Importance == MessageImportance.High) || + (_forwardTaskCommandLine && e is TaskCommandLineEventArgs); if (forwardEvent) { @@ -477,32 +365,13 @@ private void MessageHandler(object sender, BuildMessageEventArgs e) } } - /// - /// Prints a custom event - /// - private void CustomEventHandler(object sender, CustomBuildEventArgs e) - { - if (_forwardingTable[CustomEventDescription] == 1) - { - ForwardToCentralLogger(e); - } - } - - private void BuildStatusHandler(object sender, BuildStatusEventArgs e) - { - if (_forwardingTable[ProjectEvaluationEventDescription] == 1 && (e is ProjectEvaluationStartedEventArgs || e is ProjectEvaluationFinishedEventArgs)) - { - ForwardToCentralLogger(e); - } - } - /// /// Forwards the specified event. /// /// The to forward. protected virtual void ForwardToCentralLogger(BuildEventArgs e) { - _buildEventRedirector.ForwardEvent(e); + _buildEventRedirector?.ForwardEvent(e); } /// @@ -525,7 +394,7 @@ private bool IsVerbosityAtLeast(LoggerVerbosity checkVerbosity) /// /// Console logger parameters. /// - private string _loggerParameters = null; + private string? _loggerParameters = null; /// /// Console logger parameters delimiters. @@ -561,17 +430,10 @@ private bool IsVerbosityAtLeast(LoggerVerbosity checkVerbosity) #region Per-build Members - /// - /// A table indicating if a particular event type should be forwarded - /// The value is type int rather than bool to avoid the problem of JITting generics. - /// is already compiled into mscorlib. - /// - private Dictionary _forwardingTable; - /// /// A pointer to the central logger /// - private IEventRedirector _buildEventRedirector; + private IEventRedirector? _buildEventRedirector; /// /// Indicates if the events to forward are being set by the parameters sent to the logger @@ -600,6 +462,26 @@ private bool IsVerbosityAtLeast(LoggerVerbosity checkVerbosity) /// private bool _showCommandLine = false; + /// + /// Fine-tuning of BuildMessageEventArgs forwarding + /// + private bool _forwardLowImportanceMessages; + + /// + /// Fine-tuning of BuildMessageEventArgs forwarding + /// + private bool _forwardNormalImportanceMessages; + + /// + /// Fine-tuning of BuildMessageEventArgs forwarding + /// + private bool _forwardHighImportanceMessages; + + /// + /// Fine-tuning of BuildMessageEventArgs forwarding + /// + private bool _forwardTaskCommandLine; + /// /// Id of the node the logger is attached to /// diff --git a/src/Framework/IEventSource.cs b/src/Framework/IEventSource.cs index 4ba9c258238..187c105d386 100644 --- a/src/Framework/IEventSource.cs +++ b/src/Framework/IEventSource.cs @@ -152,4 +152,165 @@ public interface IEventSource /// event AnyEventHandler AnyEventRaised; } + + /// + /// Helper methods for interface. + /// + public static class EventSourceExtensions + { + /// + /// Helper method ensuring single deduplicated subscription to the event. + /// + /// + /// Handler to the event. If this handler is already subscribed, single subscription will be ensured. + public static void HandleMessageRaised(this IEventSource eventSource, BuildMessageEventHandler handler) + { + eventSource.MessageRaised -= handler; + eventSource.MessageRaised += handler; + } + + /// + /// Helper method ensuring single deduplicated subscription to the event. + /// + /// + /// Handler to the event. If this handler is already subscribed, single subscription will be ensured. + public static void HandleErrorRaised(this IEventSource eventSource, BuildErrorEventHandler handler) + { + eventSource.ErrorRaised -= handler; + eventSource.ErrorRaised += handler; + } + + /// + /// Helper method ensuring single deduplicated subscription to the event. + /// + /// + /// Handler to the event. If this handler is already subscribed, single subscription will be ensured. + public static void HandleWarningRaised(this IEventSource eventSource, BuildWarningEventHandler handler) + { + eventSource.WarningRaised -= handler; + eventSource.WarningRaised += handler; + } + + /// + /// Helper method ensuring single deduplicated subscription to the event. + /// + /// + /// Handler to the event. If this handler is already subscribed, single subscription will be ensured. + public static void HandleBuildStarted(this IEventSource eventSource, BuildStartedEventHandler handler) + { + eventSource.BuildStarted -= handler; + eventSource.BuildStarted += handler; + } + + /// + /// Helper method ensuring single deduplicated subscription to the event. + /// + /// + /// Handler to the event. If this handler is already subscribed, single subscription will be ensured. + public static void HandleBuildFinished(this IEventSource eventSource, BuildFinishedEventHandler handler) + { + eventSource.BuildFinished -= handler; + eventSource.BuildFinished += handler; + } + + /// + /// Helper method ensuring single deduplicated subscription to the event. + /// + /// + /// Handler to the event. If this handler is already subscribed, single subscription will be ensured. + public static void HandleProjectStarted(this IEventSource eventSource, ProjectStartedEventHandler handler) + { + eventSource.ProjectStarted -= handler; + eventSource.ProjectStarted += handler; + } + + /// + /// Helper method ensuring single deduplicated subscription to the event. + /// + /// + /// Handler to the event. If this handler is already subscribed, single subscription will be ensured. + public static void HandleProjectFinished(this IEventSource eventSource, ProjectFinishedEventHandler handler) + { + eventSource.ProjectFinished -= handler; + eventSource.ProjectFinished += handler; + } + + + /// + /// Helper method ensuring single deduplicated subscription to the event. + /// + /// + /// Handler to the event. If this handler is already subscribed, single subscription will be ensured. + public static void HandleTargetStarted(this IEventSource eventSource, TargetStartedEventHandler handler) + { + eventSource.TargetStarted -= handler; + eventSource.TargetStarted += handler; + } + + /// + /// Helper method ensuring single deduplicated subscription to the event. + /// + /// + /// Handler to the event. If this handler is already subscribed, single subscription will be ensured. + public static void HandleTargetFinished(this IEventSource eventSource, TargetFinishedEventHandler handler) + { + eventSource.TargetFinished -= handler; + eventSource.TargetFinished += handler; + } + + /// + /// Helper method ensuring single deduplicated subscription to the event. + /// + /// + /// Handler to the event. If this handler is already subscribed, single subscription will be ensured. + public static void HandleTaskStarted(this IEventSource eventSource, TaskStartedEventHandler handler) + { + eventSource.TaskStarted -= handler; + eventSource.TaskStarted += handler; + } + + /// + /// Helper method ensuring single deduplicated subscription to the event. + /// + /// + /// Handler to the event. If this handler is already subscribed, single subscription will be ensured. + public static void HandleTaskFinished(this IEventSource eventSource, TaskFinishedEventHandler handler) + { + eventSource.TaskFinished -= handler; + eventSource.TaskFinished += handler; + } + + /// + /// Helper method ensuring single deduplicated subscription to the event. + /// + /// + /// Handler to the event. If this handler is already subscribed, single subscription will be ensured. + public static void HandleCustomEventRaised(this IEventSource eventSource, CustomBuildEventHandler handler) + { + eventSource.CustomEventRaised -= handler; + eventSource.CustomEventRaised += handler; + } + + /// + /// Helper method ensuring single deduplicated subscription to the event. + /// + /// + /// Handler to the event. If this handler is already subscribed, single subscription will be ensured. + public static void HandleStatusEventRaised(this IEventSource eventSource, BuildStatusEventHandler handler) + { + eventSource.StatusEventRaised -= handler; + eventSource.StatusEventRaised += handler; + } + + /// + /// Helper method ensuring single deduplicated subscription to the event. + /// + /// + /// Handler to the event. If this handler is already subscribed, single subscription will be ensured. + public static void HandleAnyEventRaised(this IEventSource eventSource, AnyEventHandler handler) + { + eventSource.AnyEventRaised -= handler; + eventSource.AnyEventRaised += handler; + } + } }