CastOrConvert Method

Prometheus.Binding and other subsystems actively use this method, located at ...
In few words it translates given object in to the given type.
First, it detects if target type is Visibility (in this case false will be translated into Collapsed)
Then standart things is going on:
  1. TypeConverter attribute allows UI element owner to define how property can be converted
  2. If target type is enumerable type - Enum.Parse is used. Additionally generic type extraction is used and Nullable case takes special place.
  3. If source object is IConvertible, ToType method is doing the job
  4. Special case - ImageSource. It can be converted from array of bytes

Source code:
public static object CastOrConvert(this object obj, Type toType)
{
    if (obj == null) return null;

    if (obj.GetType() == toType) return obj;

    if ((toType == typeof (Visibility)) && (obj is bool))
    {
        return (bool) obj ? Visibility.Visible : Visibility.Collapsed;
    }

    var typeConverterAttubute =
        toType.GetCustomAttributes(typeof (TypeConverterAttribute), true).LastOrDefault() as
        TypeConverterAttribute;
    if (typeConverterAttubute != null)
    {
        Type convType = Type.GetType(typeConverterAttubute.ConverterTypeName);
        Debug.Assert(convType != null, "convType != null");
        ConstructorInfo constructorInfo = convType.GetConstructor(Type.EmptyTypes);

        if (constructorInfo == null)
            throw new InvalidOperationException(
                "Trying to convert the value by type converter, which has no default constructor: " + convType);

        var converter = (TypeConverter) constructorInfo.Invoke(new object[0]);
         if (converter.CanConvertFrom(obj.GetType()))
        {
            return converter.ConvertFrom(obj);
        }
    }
            
    if (toType.IsEnum)
    {
        try
        {
            return Enum.Parse(toType, obj.ToString(), false);
        }
        catch (ArgumentException)
        {
            throw new SomethingInvalidException();
        }
    }

    if (toType.IsGenericType)
    {
        if (toType.GetGenericArguments()[0].IsEnum)
        {
            try
            {
                return Enum.Parse(toType.GetGenericArguments()[0], obj.ToString(), false);
            }
            catch (ArgumentException)
            {
                throw new SomethingInvalidException();
            }
        }

        if (toType.GetGenericTypeDefinition() == typeof (Nullable<>))
        {
            var str = obj as string;
            if (str != null)
                if (str == string.Empty)
                {
                    return null;
                }
            toType = toType.GetGenericArguments()[0];
        }

        var convertible = obj as IConvertible;
        if (convertible != null)
        {
            return convertible.ToType(toType, null);
        }
        return obj; //.ToString(); the same as below: why to string ??
    }

    if (toType == typeof (ImageSource) && obj is byte[])
    {
        return ((byte[]) obj).ConvertToImageSource();
    }

    {
        var convertible = obj as IConvertible;
        if (convertible != null)
        {
            return convertible.ToType(toType, null);
        }
        return obj;
    }
}

Last edited Aug 16, 2012 at 12:28 PM by jinek, version 2

Comments

No comments yet.