18

I have the below code and I'd need to convert a string to a type which is also specified from String:

 Type t = Type.GetType("System.Nullable`1[[System.DateTime, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]");

            object d = Convert.ChangeType("2012-02-23 10:00:00", t);

I get the below error messagE:

Invalid cast from 'System.String' to 'System.Nullable`1[[System.DateTime, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]'.

How would that be nicely possible?

I know one ugly way would be to check whether the type is nullable using if:

    Type possiblyNullableType = Type.GetType("System.Nullable`1[[System.DateTime, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]");

    var underlyingType = Nullable.GetUnderlyingType(possiblyNullableType);

    Object result;

    // if it's null, it means it wasn't nullable
    if (underlyingType != null)
    {
        result = Convert.ChangeType("2012-02-23 10:00:00", underlyingType);
    }

Would there be any better way?

Thanks,

The Light
  • 26,341
  • 62
  • 176
  • 258

4 Answers4

34

There are two problems.

Firstly, Convert.ChangeType just plain does not support nullable types.

Secondly, even if it did, by boxing the result (assigning it to an object), you'd already be converting it to a DateTime.

You could special case nullable types:

string s = "2012-02-23 10:00:00";
Type t = Type.GetType("System.Nullable`1[[System.DateTime, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]");
object d;

if (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Nullable<>))
{
    if (String.IsNullOrEmpty(s))
        d = null;
    else
        d = Convert.ChangeType(s, t.GetGenericArguments()[0]);
}
else
{
    d = Convert.ChangeType(s, t);
}
  • Why would you need to check t.IsGenericType? the t.GetGenericTypeDefinition() == typeof(Nullable<>) part would cover that; wouldn't it? – The Light Feb 24 '12 at 12:09
  • 2
    @William `GetGenericTypeDefinition()` throws an exception if the type isn't generic. –  Feb 24 '12 at 13:41
  • Thank you so much for this elegant solution, you saved my day! – Ron Michael Mar 12 '20 at 17:36
14

I wrote the below generic helper method which works in most scenarios (not tested with generic types):

static void Main(string[] args)
{
    Object result =
        ConvertValue(
            "System.Nullable`1[[System.DateTime, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]",
            "2012-02-23 10:00:00");
}

public static Object ConvertValue(string typeInString, string value)
{
    Type originalType = Type.GetType(typeInString);

    var underlyingType = Nullable.GetUnderlyingType(originalType);

    // if underlyingType has null value, it means the original type wasn't nullable
    object instance = Convert.ChangeType(value, underlyingType ?? originalType);

    return instance;
}
The Light
  • 26,341
  • 62
  • 176
  • 258
2
public static T GetValue<T>(string Literal, T DefaultValue)
    {
        if (Literal == null || Literal == "" || Literal == string.Empty) return DefaultValue;
        IConvertible obj = Literal;
        Type t = typeof(T);
        Type u = Nullable.GetUnderlyingType(t);

        if (u != null)
        {
            return (obj == null) ? DefaultValue : (T)Convert.ChangeType(obj, u);
        }
        else
        {
            return (T)Convert.ChangeType(obj, t);
        }
    }
Hossein Shahabi
  • 327
  • 1
  • 2
  • 12
0

Something like this? Unless you really need to do it dynamically.

if (string.IsNullOrEmpty(input))
{
   return new DateTime?();
}
else
{
   return new DateTime?(DateTime.Parse(input));
}

Possibly you could check to see if your type is one of the 'nullable' types and then maybe you could find something useful here:

Convert string to nullable type (int, double, etc...)

Community
  • 1
  • 1
Paddy
  • 33,309
  • 15
  • 79
  • 114