Question #238356 on NUnit Framework changed:
https://answers.launchpad.net/nunit-3.0/+question/238356

Danil Flores posted a new comment:
The change itself is rather simple. There are two places in the code
that use Convert.ChangeType(dataValue, targetMethodParameterType, ...);
to attempt to convert convertible values into the actual type a
parameter expects.

Convert.ChangeType(...) crashes when the type is a nullable of a type,
so basically the algorithm is as follows:

1. First check if the target type is Nullable using 
Nullable.GetUnderlyingType(targetType) which just returns null if the item is 
not nullable.
2. There's a section of if statements that determine if the value is 
convertible to something by comparing the parameter type to the proposed value 
type. If the item is nullable, compare to the underlying type instead.
3. Call Convert.ChangeType(...) on either the nullabletype if not null or the 
target type.
4. If the target type is nullable, create a NullableConverter for it and 
convert the value from step 3. into a nullable of it.

Now I realize there's some conditional compilation symbols that I'd
still need to add to make sure that the assembly can still be compiled
for CLR 2.0, but here's the jist of it from
NUnitCore\core\builders\TestCaseParameterProvider.cs in NUnit v2

private static void PerformSpecialConversions(object[] arglist, ParameterInfo[] 
parameters)
{
    // Rest of code is omitted for brevity, this starts on line 151 in 
TestCaseParameterProvider.cs
    Type nullableType = Nullable.GetUnderlyingType(targetType);
    bool convert = false;
    bool isNullable = nullableType != null;
    Type typeToCompare = nullableType ?? targetType;

    if (typeToCompare == typeof(short) || typeToCompare == typeof(byte) || 
typeToCompare == typeof(sbyte))
           convert = arg is int;
    else if (typeToCompare == typeof(decimal))
           convert = arg is double || arg is string || arg is int;
    else if (typeToCompare == typeof(DateTime) || typeToCompare == 
typeof(TimeSpan))
           convert = arg is string;

    if (convert)
    {
          arglist[i] = Convert.ChangeType(arg, nullableType ?? targetType, 
System.Globalization.CultureInfo.InvariantCulture);

          if (isNullable)
          {
                 NullableConverter converter = new 
NullableConverter(targetType);
                 arglist[i] = converter.ConvertFrom(arglist[i]);
          }
    }
}

There is a similar change to NUnitTestCaseBuilder as well to ensure that
the types match up. Those were the only two areas that I found were
doing the conversion, but feel free to let me know if I've missed
something. Do you think this approach is the best way to go?

(By the way, not sure how this comment thread treats whitespace, so I
apologize if the code snippet comes out poorly formatted).


Thanks!
Danil M. Flores

-- 
You received this question notification because you are a member of
NUnit Core Developers, which is an answer contact for NUnit Framework.

_______________________________________________
Mailing list: https://launchpad.net/~nunit-core
Post to     : [email protected]
Unsubscribe : https://launchpad.net/~nunit-core
More help   : https://help.launchpad.net/ListHelp

Reply via email to