mvvmlight
mvvmlight copied to clipboard
Nullable<DataTime> causes CommandWpf to thorw exception on Execute
Reproduction Steps:
- Create an instance of
GalaSoft.MvvmLight.CommandWpf.RelayCommand<DateTime?>
- Invoke
Execute()
passing aDateTime
instance for the parameter.
Observed:
System.InvalidCastException
HResult=0x80004002
Message=Invalid cast from 'System.DateTime' to 'System.Nullable`1[[System.DateTime, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]'.
Source=mscorlib
StackTrace:
at System.Convert.DefaultToType(IConvertible value, Type targetType, IFormatProvider provider)
at System.DateTime.System.IConvertible.ToType(Type type, IFormatProvider provider)
at System.Convert.ChangeType(Object value, Type conversionType, IFormatProvider provider)
at GalaSoft.MvvmLight.CommandWpf.RelayCommand`1.Execute(Object parameter) in C:\Dev\mvvmlight\GalaSoft.MvvmLight\GalaSoft.MvvmLight (PCL)\Command\RelayCommandGeneric.cs:line 221
at GalaSoft.MvvmLight.Test.Command.RelayCommandGenericTest.TestNullableDateTimeConversionExecute() in C:\Dev\mvvmlight\GalaSoft.MvvmLight\Tests\PCL\GalaSoft.MvvmLight.Test (PNET45)\Command\RelayCommandGenericTest.cs:line 347
Expected: The command should execute.
The problem appears to be specific to the RelayCommand<T>
when compiled with !NETFX_CORE
.
Specifically this section in the RelayCommand<T>.Execute()
.
#if !NETFX_CORE
if (parameter != null
&& parameter.GetType() != typeof(T))
{
if (parameter is IConvertible)
{
val = Convert.ChangeType(parameter, typeof (T), null);
}
}
#endif
This is problematic when the generic parameter is Nullable<DateTime> and the passed in parameter is a a boxed instance of DateTime.
Unit Tests:
[TestMethod]
public void TestNullableDateTimeConversionCanExecute()
{
var today = DateTime.Today;
var command = new CommandWpf.RelayCommand<DateTime?>(
x => _methodWasExecuted = true,
x => x == today);
Assert.IsTrue(command.CanExecute(today));
}
[TestMethod]
public void TestNullableDateTimeConversionExecute()
{
var today = DateTime.Today;
DateTime? executedParameter = null;
var command = new CommandWpf.RelayCommand<DateTime?>(
x =>
{
executedParameter = x;
_methodWasExecuted = true;
});
command.Execute(today);
Assert.IsTrue(_methodWasExecuted);
Assert.AreEqual(today, executedParameter);
}
Proposed fix:
#if !NETFX_CORE
if (parameter != null && !(parameter is T) && parameter is IConvertible)
{
val = Convert.ChangeType(parameter, typeof (T), null);
}
#endif