← Back to team overview

nunit-core team mailing list archive

Re: [Question #238356]: Looking to implement NUnit 2.6.x feature for MBUnit to NUnit Conversion

 

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.