Example #1
0
        /// <summary>Used to cast the return value of a native call to something useful.</summary>
        /// <remarks>This is better than a C# cast because it will produce a decent error message
        /// if there are problems and it will convert native IntPtr objects to the corresponding managed
        /// object.</remarks>
        public static T To <T>(this object value)
        {
            // If the value is null then return some form of null.
            if (value == null || value.Equals(IntPtr.Zero))
            {
                if (typeof(T).IsValueType)
                {
                    throw new InvalidCastException("Value is null");
                }

                else if (typeof(T) == typeof(NSObject))
                {
                    return((T)(object)new NSObject(IntPtr.Zero));
                }

                else if (typeof(NSObject).IsAssignableFrom(typeof(T)))
                {
                    return((T)Activator.CreateInstance(typeof(T), BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public, null,
                                                       new object[] { IntPtr.Zero }, null));
                }

                else
                {
                    return(default(T));
                }
            }

            // If T matches the value type then just cast value to that type.
            Type type = value.GetType();

            if (type == typeof(T))
            {
                return((T)value);
            }

            // If T is bool then allow value to be an sbyte.
            if (typeof(T) == typeof(bool) && type == typeof(sbyte))
            {
                return((T)(object)((sbyte)value != 0));
            }

            // If T is NSObject, a derived class, or IntPtr then do a lookup and
            // return the correct managed class.
            if (type == typeof(IntPtr) || typeof(NSObject).IsAssignableFrom(typeof(T)))
            {
                IntPtr instance = IntPtr.Zero;
                if (type == typeof(IntPtr))
                {
                    instance = (IntPtr)value;
                }
                else
                {
                    instance = (IntPtr)(NSObject)value;
                }

                NSObject obj = NSObject.Lookup(instance);
                if (obj == null)
                {
                    return(default(T));
                }
                else if (typeof(T).IsAssignableFrom(obj.GetType()))
                {
                    return((T)(object)obj);
                }
                else
                {
                    throw new InvalidCastException("Can't cast from " + obj.class_().Name + " to " + typeof(T) + ".");
                }
            }

            throw new InvalidCastException("Can't cast from " + type + " to " + typeof(T) + ".");
        }