diff options
author | E.Z. Hart <hartez@users.noreply.github.com> | 2016-12-01 14:15:17 -0700 |
---|---|---|
committer | Stephane Delcroix <stephane@delcroix.org> | 2016-12-01 22:15:17 +0100 |
commit | 46c25a2edbf257153d7bb33d2ac3997a3718e3ee (patch) | |
tree | 92209a25a152c11af33684c1e1933514ac4c407a /Xamarin.Forms.Core/Command.cs | |
parent | 3d85653f270854b4aab82e45e6e58afb760feb85 (diff) | |
download | xamarin-forms-46c25a2edbf257153d7bb33d2ac3997a3718e3ee.tar.gz xamarin-forms-46c25a2edbf257153d7bb33d2ac3997a3718e3ee.tar.bz2 xamarin-forms-46c25a2edbf257153d7bb33d2ac3997a3718e3ee.zip |
Don't run Command CanExecute on incorrect inherited binding context type (#572)
* Allow Command CanExecute to recover when run on inherited bindingcontext
* Make exception handler more generic
* Checking types in Command delegates to avoid exception in the first place
* Adding type chekc to other Command constructor
* Use nameof for ArgumentNullExceptions
* Add unit tests for null parameters, handle value types and Nullable<T>
Diffstat (limited to 'Xamarin.Forms.Core/Command.cs')
-rw-r--r-- | Xamarin.Forms.Core/Command.cs | 62 |
1 files changed, 49 insertions, 13 deletions
diff --git a/Xamarin.Forms.Core/Command.cs b/Xamarin.Forms.Core/Command.cs index 73ae1b08..d15574cf 100644 --- a/Xamarin.Forms.Core/Command.cs +++ b/Xamarin.Forms.Core/Command.cs @@ -1,22 +1,59 @@ using System; +using System.Reflection; using System.Windows.Input; namespace Xamarin.Forms { - public sealed class Command<T> : Command + public sealed class Command<T> : Command { - public Command(Action<T> execute) : base(o => execute((T)o)) + public Command(Action<T> execute) + : base(o => + { + if (IsValidParameter(o)) + { + execute((T)o); + } + }) { if (execute == null) - throw new ArgumentNullException("execute"); + { + throw new ArgumentNullException(nameof(execute)); + } } - public Command(Action<T> execute, Func<T, bool> canExecute) : base(o => execute((T)o), o => canExecute((T)o)) + public Command(Action<T> execute, Func<T, bool> canExecute) + : base(o => + { + if (IsValidParameter(o)) + { + execute((T)o); + } + }, o => IsValidParameter(o) && canExecute((T)o)) { if (execute == null) - throw new ArgumentNullException("execute"); + throw new ArgumentNullException(nameof(execute)); if (canExecute == null) - throw new ArgumentNullException("canExecute"); + throw new ArgumentNullException(nameof(canExecute)); + } + + static bool IsValidParameter(object o) + { + if (o != null) + { + // The parameter isn't null, so we don't have to worry whether null is a valid option + return o is T; + } + + var t = typeof(T); + + // The parameter is null. Is T Nullable? + if (Nullable.GetUnderlyingType(t) != null) + { + return true; + } + + // Not a Nullable, if it's a value type then null is not valid + return !t.GetTypeInfo().IsValueType; } } @@ -28,7 +65,7 @@ namespace Xamarin.Forms public Command(Action<object> execute) { if (execute == null) - throw new ArgumentNullException("execute"); + throw new ArgumentNullException(nameof(execute)); _execute = execute; } @@ -36,13 +73,13 @@ namespace Xamarin.Forms public Command(Action execute) : this(o => execute()) { if (execute == null) - throw new ArgumentNullException("execute"); + throw new ArgumentNullException(nameof(execute)); } public Command(Action<object> execute, Func<object, bool> canExecute) : this(execute) { if (canExecute == null) - throw new ArgumentNullException("canExecute"); + throw new ArgumentNullException(nameof(canExecute)); _canExecute = canExecute; } @@ -50,9 +87,9 @@ namespace Xamarin.Forms public Command(Action execute, Func<bool> canExecute) : this(o => execute(), o => canExecute()) { if (execute == null) - throw new ArgumentNullException("execute"); + throw new ArgumentNullException(nameof(execute)); if (canExecute == null) - throw new ArgumentNullException("canExecute"); + throw new ArgumentNullException(nameof(canExecute)); } public bool CanExecute(object parameter) @@ -73,8 +110,7 @@ namespace Xamarin.Forms public void ChangeCanExecute() { EventHandler changed = CanExecuteChanged; - if (changed != null) - changed(this, EventArgs.Empty); + changed?.Invoke(this, EventArgs.Empty); } } }
\ No newline at end of file |