/// <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) + "."); }