public bool TryChangeType (object value, Type type, CultureInfo culture, out object ret)
{
ScriptObject script_object;
ret = value;
if (value == null)
return true;
if (value.GetType() == type)
return true;
// we need to do this before the ScriptObject
// block because we might be passing
// ManagedObject arguments to a method that
// takes ScriptObjects, and therefore we
// shouldn't "unwrap" the ScriptObject's
// ManagedObject field.
if (type.IsAssignableFrom (value.GetType ()))
return true;
script_object = value as ScriptObject;
if (script_object != null) {
value = script_object.ManagedObject;
if (value == null && type == typeof(HtmlElement))
value = new HtmlElement (script_object.Handle);
ret = value;
if (value.GetType () == type)
return true;
}
if (type.IsAssignableFrom (value.GetType ()))
return true;
if (type == typeof (ScriptObject)) {
ret = new ManagedObject (value);
return true;
}
if (type.IsEnum) {
try {
ret = Enum.Parse (type, value.ToString(), true);
return true;
} catch {
return false;
}
}
/* the set of source types for JS functions is
* very, very small, so we switch over the
* parameter type first */
try {
ret = Convert.ChangeType (value, type, culture);
return true;
}
catch {
// no clue if this is right.. if we
// fail to convert, what do we return?
switch (Type.GetTypeCode (type))
{
case TypeCode.Char:
case TypeCode.Byte:
case TypeCode.SByte:
case TypeCode.Int16:
case TypeCode.Int32:
case TypeCode.Int64:
case TypeCode.UInt16:
case TypeCode.UInt32:
case TypeCode.UInt64:
case TypeCode.Single:
case TypeCode.Double:
ret = Convert.ChangeType (0, type, culture);
return true;
case TypeCode.String:
ret = "";
return true;
case TypeCode.Boolean:
ret = false;
return true;
}
}
return false;
}