< Summary

Information
Class: MyNet.Messaging.WeakAction
Assembly: MyNet.Messaging
File(s): https://raw.githubusercontent.com/sandre58/MyNet/85372080fe102cd9ee155ceab49ae000e7f66103/src/MyNet.Messaging/WeakAction.cs
Tag: 323_28699572109
Line coverage
82%
Covered lines: 32
Uncovered lines: 7
Coverable lines: 39
Total lines: 242
Line coverage: 82%
Branch coverage
65%
Covered branches: 26
Total branches: 40
Branch coverage: 65%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%11100%
.ctor(...)83.33%6690%
get_IsStatic()100%11100%
get_MethodName()33.33%66100%
get_IsAlive()71.42%161480%
get_Target()50%22100%
get_ActionTarget()50%44100%
Execute()75%13858.33%
MarkForDeletion()100%11100%

File(s)

https://raw.githubusercontent.com/sandre58/MyNet/85372080fe102cd9ee155ceab49ae000e7f66103/src/MyNet.Messaging/WeakAction.cs

#LineLine coverage
 1// -----------------------------------------------------------------------
 2// <copyright file="WeakAction.cs" company="Stéphane ANDRE">
 3// Copyright (c) Stéphane ANDRE. All rights reserved.
 4// </copyright>
 5// -----------------------------------------------------------------------
 6
 7using System;
 8using System.Reflection;
 9
 10namespace MyNet.Messaging;
 11
 12/// <summary>
 13/// Stores an <see cref="Action" /> without causing a hard reference
 14/// to be created to the Action's owner. The owner can be garbage collected at any time.
 15/// </summary>
 16public class WeakAction
 17{
 18    private Action? _staticAction;
 19    private WeakReference? _targetReference;
 20    private WeakReference? _actionTargetReference;
 21    private object? _liveReference;
 22    private MethodInfo? _method;
 23
 24    public WeakAction(Action action, bool keepTargetAlive = false)
 1525        : this(action.Target, action, keepTargetAlive)
 26    {
 1527    }
 28
 29    public WeakAction(object? target, Action action, bool keepTargetAlive = false)
 30    {
 2131        if (action.Method.IsStatic)
 32        {
 633            _staticAction = action;
 634            if (target != null)
 035                _targetReference = new(target);
 636            return;
 37        }
 38
 1539        _method = action.Method;
 1540        _actionTargetReference = new(action.Target);
 1541        _liveReference = keepTargetAlive ? action.Target : null;
 1542        _targetReference = new(target);
 1543    }
 44
 45    /// <summary>
 46    /// Gets a value indicating whether the WeakAction is static or not.
 47    /// </summary>
 348    public bool IsStatic => _staticAction != null;
 49
 50    /// <summary>
 51    /// Gets the name of the method that this WeakAction represents.
 52    /// </summary>
 353    public virtual string? MethodName => _staticAction?.Method.Name ?? _method?.Name;
 54
 55    /// <summary>
 56    /// Gets a value indicating whether the Action's owner is still alive, or if it was collected
 57    /// by the Garbage Collector already.
 58    /// </summary>
 59    public virtual bool IsAlive
 60    {
 61        get
 62        {
 1263            if (_staticAction == null && _targetReference == null && _liveReference == null)
 364                return false;
 65
 966            if (_staticAction != null)
 067                return _targetReference?.IsAlive != false;
 68
 69            // Non static action
 970            return _liveReference != null || _targetReference is { IsAlive: true };
 71        }
 72    }
 73
 74    /// <summary>
 75    /// Gets the Action's owner. This object is stored as a WeakReference.
 76    /// </summary>
 677    public object? Target => _targetReference?.Target;
 78
 379    protected object? ActionTarget => _liveReference ?? _actionTargetReference?.Target;
 80
 81    /// <summary>
 82    /// Executes the action. This only happens if the action's owner is still alive.
 83    /// </summary>
 84    public void Execute()
 85    {
 386        if (!IsAlive)
 087            return;
 88
 389        if (_staticAction != null)
 90        {
 091            _staticAction();
 092            return;
 93        }
 94
 395        var actionTarget = ActionTarget;
 396        if (_method != null && actionTarget != null)
 97        {
 98            try
 99            {
 3100                _ = _method.Invoke(actionTarget, null);
 3101            }
 0102            catch
 103            {
 104                // Silently ignore invocation errors
 0105            }
 106        }
 3107    }
 108
 109    /// <summary>
 110    /// Sets all references to null, marking this WeakAction for deletion.
 111    /// </summary>
 112    public void MarkForDeletion()
 113    {
 3114        _staticAction = null;
 3115        _targetReference = null;
 3116        _actionTargetReference = null;
 3117        _liveReference = null;
 3118        _method = null;
 3119    }
 120}
 121
 122/// <summary>
 123/// Stores a generic Action&lt;T&gt; without causing a hard reference
 124/// to be created to the Action's owner. The owner can be garbage collected at any time.
 125/// </summary>
 126/// <typeparam name="T">The type of the Action's parameter.</typeparam>
 127public class WeakAction<T> : IExecuteWithObject
 128{
 129    private Action<T?>? _staticAction;
 130    private WeakReference? _targetReference;
 131    private WeakReference? _actionTargetReference;
 132    private object? _liveReference;
 133    private MethodInfo? _method;
 134
 135    public WeakAction(Action<T?> action, bool keepTargetAlive = false)
 136        : this(action.Target, action, keepTargetAlive)
 137    {
 138    }
 139
 140    public WeakAction(object? target, Action<T?> action, bool keepTargetAlive = false)
 141    {
 142        if (action.Method.IsStatic)
 143        {
 144            _staticAction = action;
 145            if (target != null)
 146                _targetReference = new(target);
 147            return;
 148        }
 149
 150        _method = action.Method;
 151        _actionTargetReference = new(action.Target);
 152        _liveReference = keepTargetAlive ? action.Target : null;
 153        _targetReference = new(target);
 154    }
 155
 156    /// <summary>
 157    /// Gets the name of the method that this WeakAction represents.
 158    /// </summary>
 159    public string? MethodName => _staticAction?.Method.Name ?? _method?.Name;
 160
 161    /// <summary>
 162    /// Gets a value indicating whether the Action's owner is still alive.
 163    /// </summary>
 164    public bool IsAlive =>
 165        (_staticAction != null || _targetReference != null || _liveReference != null) && (_staticAction != null ? _targe
 166
 167    /// <summary>
 168    /// Gets the Action's owner. This object is stored as a WeakReference.
 169    /// </summary>
 170    public object? Target => _targetReference?.Target;
 171
 172    protected object? ActionTarget => _liveReference ?? _actionTargetReference?.Target;
 173
 174    /// <summary>
 175    /// Executes the action. This only happens if the action's owner is still alive.
 176    /// The action's parameter is set to default(T).
 177    /// </summary>
 178    public void Execute() => Execute(default);
 179
 180    /// <summary>
 181    /// Executes the action. This only happens if the action's owner is still alive.
 182    /// </summary>
 183    /// <param name="parameter">A parameter to be passed to the action.</param>
 184    public void Execute(T? parameter)
 185    {
 186        if (!IsAlive)
 187            return;
 188
 189        if (_staticAction != null)
 190        {
 191            try
 192            {
 193                _staticAction(parameter);
 194            }
 195            catch
 196            {
 197                // Silently ignore invocation errors
 198            }
 199
 200            return;
 201        }
 202
 203        var actionTarget = ActionTarget;
 204        if (_method != null && actionTarget != null)
 205        {
 206            try
 207            {
 208                _ = _method.Invoke(actionTarget, [parameter]);
 209            }
 210            catch
 211            {
 212                // Silently ignore invocation errors
 213            }
 214        }
 215    }
 216
 217    /// <summary>
 218    /// Executes the action with a parameter of type object. This parameter
 219    /// will be casted to T. This method implements <see cref="IExecuteWithObject.ExecuteWithObject" />
 220    /// and can be useful if you store multiple WeakAction{T} instances but don't know in advance
 221    /// what type T represents.
 222    /// </summary>
 223    /// <param name="parameter">The parameter that will be passed to the action after being casted to T.</param>
 224    public void ExecuteWithObject(object? parameter)
 225    {
 226        var parameterCasted = (T?)parameter;
 227        Execute(parameterCasted);
 228    }
 229
 230    /// <summary>
 231    /// Sets all references to null, marking this WeakAction for deletion.
 232    /// </summary>
 233    public void MarkForDeletion()
 234    {
 235        _staticAction = null;
 236        _targetReference = null;
 237        _actionTargetReference = null;
 238        _liveReference = null;
 239        _method = null;
 240    }
 241}
 242