< Summary

Information
Class: MyNet.Messaging.WeakAction<T>
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: 34
Uncovered lines: 7
Coverable lines: 41
Total lines: 242
Line coverage: 82.9%
Branch coverage
70%
Covered branches: 28
Total branches: 40
Branch coverage: 70%
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_MethodName()83.33%66100%
get_IsAlive()57.14%1414100%
get_Target()50%22100%
get_ActionTarget()75%44100%
Execute()100%11100%
Execute(...)75%12860%
ExecuteWithObject(...)100%11100%
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)
 25        : this(action.Target, action, keepTargetAlive)
 26    {
 27    }
 28
 29    public WeakAction(object? target, Action action, bool keepTargetAlive = false)
 30    {
 31        if (action.Method.IsStatic)
 32        {
 33            _staticAction = action;
 34            if (target != null)
 35                _targetReference = new(target);
 36            return;
 37        }
 38
 39        _method = action.Method;
 40        _actionTargetReference = new(action.Target);
 41        _liveReference = keepTargetAlive ? action.Target : null;
 42        _targetReference = new(target);
 43    }
 44
 45    /// <summary>
 46    /// Gets a value indicating whether the WeakAction is static or not.
 47    /// </summary>
 48    public bool IsStatic => _staticAction != null;
 49
 50    /// <summary>
 51    /// Gets the name of the method that this WeakAction represents.
 52    /// </summary>
 53    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        {
 63            if (_staticAction == null && _targetReference == null && _liveReference == null)
 64                return false;
 65
 66            if (_staticAction != null)
 67                return _targetReference?.IsAlive != false;
 68
 69            // Non static action
 70            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>
 77    public object? Target => _targetReference?.Target;
 78
 79    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    {
 86        if (!IsAlive)
 87            return;
 88
 89        if (_staticAction != null)
 90        {
 91            _staticAction();
 92            return;
 93        }
 94
 95        var actionTarget = ActionTarget;
 96        if (_method != null && actionTarget != null)
 97        {
 98            try
 99            {
 100                _ = _method.Invoke(actionTarget, null);
 101            }
 102            catch
 103            {
 104                // Silently ignore invocation errors
 105            }
 106        }
 107    }
 108
 109    /// <summary>
 110    /// Sets all references to null, marking this WeakAction for deletion.
 111    /// </summary>
 112    public void MarkForDeletion()
 113    {
 114        _staticAction = null;
 115        _targetReference = null;
 116        _actionTargetReference = null;
 117        _liveReference = null;
 118        _method = null;
 119    }
 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)
 24136        : this(action.Target, action, keepTargetAlive)
 137    {
 24138    }
 139
 140    public WeakAction(object? target, Action<T?> action, bool keepTargetAlive = false)
 141    {
 153142        if (action.Method.IsStatic)
 143        {
 3144            _staticAction = action;
 3145            if (target != null)
 0146                _targetReference = new(target);
 3147            return;
 148        }
 149
 150150        _method = action.Method;
 150151        _actionTargetReference = new(action.Target);
 150152        _liveReference = keepTargetAlive ? action.Target : null;
 150153        _targetReference = new(target);
 150154    }
 155
 156    /// <summary>
 157    /// Gets the name of the method that this WeakAction represents.
 158    /// </summary>
 15159    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 =>
 549165        (_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>
 162170    public object? Target => _targetReference?.Target;
 171
 105172    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>
 3178    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    {
 105186        if (!IsAlive)
 0187            return;
 188
 105189        if (_staticAction != null)
 190        {
 191            try
 192            {
 0193                _staticAction(parameter);
 0194            }
 0195            catch
 196            {
 197                // Silently ignore invocation errors
 0198            }
 199
 0200            return;
 201        }
 202
 105203        var actionTarget = ActionTarget;
 105204        if (_method != null && actionTarget != null)
 205        {
 206            try
 207            {
 105208                _ = _method.Invoke(actionTarget, [parameter]);
 99209            }
 6210            catch
 211            {
 212                // Silently ignore invocation errors
 6213            }
 214        }
 105215    }
 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    {
 96226        var parameterCasted = (T?)parameter;
 96227        Execute(parameterCasted);
 96228    }
 229
 230    /// <summary>
 231    /// Sets all references to null, marking this WeakAction for deletion.
 232    /// </summary>
 233    public void MarkForDeletion()
 234    {
 33235        _staticAction = null;
 33236        _targetReference = null;
 33237        _actionTargetReference = null;
 33238        _liveReference = null;
 33239        _method = null;
 33240    }
 241}
 242