This class used with ActivityMonitorBridge, enables IActivityMonitor to relay logs. Each activity monitor exposes such a bridge target on its output thanks to IActivityMonitorOutput.BridgeTarget.
 /// <summary>
 /// Initialize a new <see cref="ActivityMonitorBridge"/> bound to an existing <see cref="ActivityMonitorBridgeTarget"/>
 /// This Client should be registered in the <see cref="IActivityMonitor.Output"/> of a local monitor.
 /// </summary>
 /// <param name="bridge">The target bridge.</param>
 /// <param name="pullTargetTopicAndAutoTagsFromTarget">
 /// When true, the <see cref="IActivityMonitor.Topic"/> and <see cref="IActivityMonitor.AutoTags"/> are automaticaly updated whenever they change on the target monitor.
 /// </param>
 /// <param name="pushTopicAndAutoTagsToTarget">
 /// When true, any change to <see cref="IActivityMonitor.Topic"/> or <see cref="IActivityMonitor.AutoTags"/> are applied to the target monitor.
 /// </param>
 /// <param name="applyTargetFilterToUnfilteredLogs">
 /// True to avoid sending logs with level below the target <see cref="IActivityMonitor.MinimalFilter"/> (when <see cref="ActivityMonitorBridgeTarget.HonorMonitorFilter"/> is true
 /// and it is an unfiltered line or group log).
 /// This is an optimization that can be used to send less data to the target monitor but breaks the UnfilteredLog/UnfilteredOpenGroup contract.
 /// </param>
 public ActivityMonitorBridge( ActivityMonitorBridgeTarget bridge, bool pullTargetTopicAndAutoTagsFromTarget, bool pushTopicAndAutoTagsToTarget, bool applyTargetFilterToUnfilteredLogs = false )
 {
     if( bridge == null ) throw new ArgumentNullException( "bridge" );
     _bridgeTarget = bridge;
     _pullTargetTopicAndAutoTagsFromTarget = pullTargetTopicAndAutoTagsFromTarget;
     _pushTopicAndAutoTagsToTarget = pushTopicAndAutoTagsToTarget;
     _applyTargetFilterToUnfilteredLogs = applyTargetFilterToUnfilteredLogs;
     _targetMonitor = _bridgeTarget.TargetMonitor;
     _openedGroups = new List<bool>();
 }
 /// <summary>
 /// Initialize a new <see cref="ActivityMonitorBridge"/> bound to an existing <see cref="ActivityMonitorBridgeTarget"/>
 /// This Client should be registered in the <see cref="IActivityMonitor.Output"/> of a local monitor.
 /// </summary>
 /// <param name="bridge">The target bridge.</param>
 /// <param name="pullTargetTopicAndAutoTagsFromTarget">
 /// When true, the <see cref="IActivityMonitor.Topic"/> and <see cref="IActivityMonitor.AutoTags"/> are automaticaly updated whenever they change on the target monitor.
 /// </param>
 /// <param name="pushTopicAndAutoTagsToTarget">
 /// When true, any change to <see cref="IActivityMonitor.Topic"/> or <see cref="IActivityMonitor.AutoTags"/> are applied to the target monitor.
 /// </param>
 /// <param name="applyTargetFilterToUnfilteredLogs">
 /// True to avoid sending logs with level below the target <see cref="IActivityMonitor.MinimalFilter"/> (when <see cref="ActivityMonitorBridgeTarget.HonorMonitorFilter"/> is true
 /// and it is an unfiltered line or group log).
 /// This is an optimization that can be used to send less data to the target monitor but breaks the UnfilteredLog/UnfilteredOpenGroup contract.
 /// </param>
 public ActivityMonitorBridge(ActivityMonitorBridgeTarget bridge, bool pullTargetTopicAndAutoTagsFromTarget, bool pushTopicAndAutoTagsToTarget, bool applyTargetFilterToUnfilteredLogs = false)
 {
     if (bridge == null)
     {
         throw new ArgumentNullException("bridge");
     }
     _bridgeTarget = bridge;
     _pullTargetTopicAndAutoTagsFromTarget = pullTargetTopicAndAutoTagsFromTarget;
     _pushTopicAndAutoTagsToTarget         = pushTopicAndAutoTagsToTarget;
     _applyTargetFilterToUnfilteredLogs    = applyTargetFilterToUnfilteredLogs;
     _targetMonitor = _bridgeTarget.TargetMonitor;
     _openedGroups  = new List <bool>();
 }
        /// <summary>
        /// Creates a bridge to another monitor's <see cref="ActivityMonitorBridgeTarget"/>. Only one bridge to the same monitor can exist at a time: if <see cref="FindBridgeTo"/> is not null,
        /// this throws a <see cref="InvalidOperationException"/>.
        /// This bridge does not synchronize <see cref="IActivityMonitor.AutoTags"/> and <see cref="IActivityMonitor.Topic"/> (see <see cref="CreateStrongBridgeTo"/>).
        /// </summary>
        /// <param name="this">This <see cref="IActivityMonitorOutput"/>.</param>
        /// <param name="targetBridge">The target bridge that will receive our logs.</param>
        /// <returns>A <see cref="IDisposable"/> object that can be disposed to automatically call <see cref="UnbridgeTo"/>.</returns>
        public static IDisposable CreateBridgeTo(this IActivityMonitorOutput @this, ActivityMonitorBridgeTarget targetBridge)
        {
            if (targetBridge == null)
            {
                throw new ArgumentNullException("targetBridge");
            }
            if (@this.Clients.OfType <ActivityMonitorBridge>().Any(b => b.BridgeTarget == targetBridge))
            {
                throw new InvalidOperationException();
            }
            var created = @this.RegisterClient(new ActivityMonitorBridge(targetBridge, false, false));

            return(Util.CreateDisposableAction(() => @this.UnregisterClient(created)));
        }
 /// <summary>
 /// Removes an existing <see cref="ActivityMonitorBridge"/> to another monitor if it exists (silently ignores it if not found).
 /// </summary>
 /// <param name="this">This <see cref="IActivityMonitorOutput"/>.</param>
 /// <param name="targetBridge">The target bridge that will no more receive our logs.</param>
 /// <returns>The unregistered <see cref="ActivityMonitorBridge"/> if found, null otherwise.</returns>
 public static ActivityMonitorBridge UnbridgeTo(this IActivityMonitorOutput @this, ActivityMonitorBridgeTarget targetBridge)
 {
     if (targetBridge == null)
     {
         throw new ArgumentNullException("targetBridge");
     }
     return(UnregisterClient <ActivityMonitorBridge>(@this, b => b.BridgeTarget == targetBridge));
 }
 /// <summary>
 /// Finds an existing bridge to another monitor.
 /// </summary>
 /// <param name="this">This <see cref="IActivityMonitorOutput"/>.</param>
 /// <param name="targetBridge">The target bridge that receives our logs.</param>
 /// <returns>The existing <see cref="ActivityMonitorBridge"/> or null if no such bridge exists.</returns>
 public static ActivityMonitorBridge FindBridgeTo(this IActivityMonitorOutput @this, ActivityMonitorBridgeTarget targetBridge)
 {
     if (targetBridge == null)
     {
         throw new ArgumentNullException("targetBridge");
     }
     return(@this.Clients.OfType <ActivityMonitorBridge>().FirstOrDefault(b => b.BridgeTarget == targetBridge));
 }