Ensure that ICommand implementation properly uses weak references
The implementation works fine if the passed delegate is an instance method, because that prevents the method from being garbage collected.

But that is not necessarily the case. Lambda expression, for instance, will be garbage collected sometime because they are not referenced somewhere else. 
That may result in strange not reproducible bugs that are hard to debug.

The following code (with a simplified version of the WeakRelayCommand class) shows that the weak reference approach does not work for static methods and lambda expressions with closures.

void Main()
{
    var longLiveObject = new DummyObject();
    var commands = GetActions(longLiveObject);

    GC.Collect();
    GC.WaitForPendingFinalizers();

    foreach (var command in commands)
        Console.WriteLine(command.Name + "\t IsAlive:" + command.IsAlive);
}

private static WeakAction[] GetActions(DummyObject longLiveObject)
{
    var localObj = new DummyObject();
    return new []
    {
        new WeakAction("InstanceMethod (short living)", localObj.InstanceMethod),
        new WeakAction("InstanceMethod (long living)", longLiveObject.InstanceMethod),
        new WeakAction("StaticMethod", DummyObject.StaticMethod),
        new WeakAction("LamdaExpression (without closure)", o =&gt; { }),
        new WeakAction("LamdaExpression (with closure)", o =&gt; localObj.InstanceMethod(o)),
    };
}

// Define other methods and classes here
public class DummyObject
{
    public void InstanceMethod(object obj) { }
    public static void StaticMethod(object obj) {}  
}

public class WeakAction
{
    private readonly WeakReference&lt;object&gt; _targetReference;
    private readonly MethodInfo _callbackInfo;

    public WeakAction(string name, Action&lt;object&gt; executeCallback)
    {
        Name = name;
        _targetReference = new WeakReference&lt;object&gt;(executeCallback.Target);
        _callbackInfo = executeCallback.GetMethodInfo();        
    }

    public string Name { get; }
    public bool IsAlive
    {
        get
        {
            object obj;
            return _targetReference.TryGetTarget(out obj);
        }
    }
}


Output:

InstanceMethod (short living)        IsAlive:False
InstanceMethod (long living)         IsAlive:True 
StaticMethod                        IsAlive:False 
LamdaExpression (without closure)   IsAlive:True 
LamdaExpression (with closure)      IsAlive:False