views:

742

answers:

4

This is a follow-up to this question about converting values with reflection. Converting an object of a certain type to another type can be done like this:

object convertedValue = Convert.ChangeType(value, targetType);

Given two Type instances (say FromType and ToType), is there a way to test whether the conversion will succeed?

E.g. can I write an extension method like this:

public static class TypeExtensions
{
    public static bool CanChangeType(this Type fromType, Type toType)
    {
        // what to put here?
    }
}

EDIT: This is what I have right now. Ugly, but I don't see another way yet...

bool CanChangeType(Type sourceType, Type targetType)
{
  try
  {
    var instanceOfSourceType = Activator.CreateInstance(sourceType);
    Convert.ChangeType(instanceOfSourceType, targetType);
    return true; // OK, it can be converted
  }
  catch (Exception ex)
  {
    return false;
  }
+1  A: 

Checking the method Convert.ChangeType in reflector I found this in the static constructor:

ConvertTypes = new Type[] { 
        typeof(Empty), typeof(object), typeof(DBNull), typeof(bool), typeof(char), typeof(sbyte), typeof(byte), typeof(short), typeof(ushort), typeof(int), typeof(uint), typeof(long), typeof(ulong), typeof(float), typeof(double), typeof(decimal), 
        typeof(DateTime), typeof(object), typeof(string)
     };

In the end, this method is just checking either if the source is implementing IConvertible or if the target is one of the ConvertTypes above. So your method should look something like this (very rough):

return (ConvertTypes.Contains(toType) || typeof(IConvertible).IsAssignableFrom(fromType));
Marc Wittke
Similar to what I mentioned in my comment above. Unfortunately, checking that the `Type` implements `IConvertible` isn't enough. There's still no guarantee that any attempted conversion will actually succeed.
LukeH
+1  A: 

I have written a little framework that includes a Convert class that can do more than the System.Convert class. If you are interested in using it, you can download it from my website. It doesn't have the ability to determine if you can convert between values, but that seems like a good feature to add.

It does include the ability to convert values based on:

  • IConvertible
  • TypeConverters
  • ToXxx methods
  • Parse static methods
  • Parameterized constructor
  • and a few other minor ones

BizArk Feature Spotlight – Data Type Conversions

Brian
Looks interesting. I'll check it out.
jeroenh
A: 

There seems to be no way provided out of the box. The code snippet I already posted in my edited question does the trick in my case:

bool CanChangeType(Type sourceType, Type targetType)
{
try
{
   var instanceOfSourceType = Activator.CreateInstance(sourceType);
   Convert.ChangeType(instanceOfSourceType, targetType);
   return true; // OK, it can be converted
 }
 catch (Exception ex)
 {
    return false;
 }

The BizArk framework from bbrewder is cool, but (a) does not have this feature yet and (b) is a bit overkill for me right now to extend.

jeroenh
Won't this just test is the default instance of a type can be converted?
neontapir
Actually, yes. As stated, this did the trick for me but you're right of course that this is not a general solution...
jeroenh
I'm sorry to down vote you but I can't see catching an exception as an acceptable solution. Just test the performance of this in a loop with even just a fraction of values that fail the test and you will see why this isn't a good idea.
jpierson
@jpierson Your argument is a bit lame. I have clearly stated that this is not a good solution, but there seems to be no alternative. If you can provide an alternative I would be happy to accept that as an answer.
jeroenh