///Returns a function that can convert from source type to target type with given func as the current value public static ValueHandler <T> GetConverterFuncFromTo <T>(Type sourceType, Type targetType, ValueHandler <object> func) { //assignables or upcasting if (targetType.RTIsAssignableFrom(sourceType) || targetType.RTIsSubclassOf(sourceType)) { return(() => { return (T)func(); }); } //convertibles if (typeof(IConvertible).RTIsAssignableFrom(targetType) && typeof(IConvertible).RTIsAssignableFrom(sourceType)) { return(() => { return (T)Convert.ChangeType(func(), targetType); }); } //handles implicit/explicit and prety much everything else. //invoke done with reflection to support all platforms. UnaryExpression exp = null; if (ReflectionTools.CanConvert(sourceType, targetType, out exp)) { return(() => { try { return (T)exp.Method.Invoke(null, new object[] { func() }); } catch { return default(T); } }); } ///CUSTOM CONVENIENCE CONVERSIONS ///---------------------------------------------------------------------------------------------- //from anything to string if (targetType == typeof(string)) { return(() => { try { return (T)(object)(func().ToString()); } catch { return default(T); } }); } //from anything to Type if (targetType == typeof(Type)) { return(() => { try { return (T)(object)func().GetType(); } catch { return default(T); } }); } //from convertible to Vector3 if (targetType == typeof(Vector3) && typeof(IConvertible).RTIsAssignableFrom(sourceType)) { return(() => { var f = (float)Convert.ChangeType(func(), typeof(float)); return (T)(object)new Vector3(f, f, f); }); } ///---------------------------------------------------------------------------------------------- //from component to Vector3 (position) if (targetType == typeof(Vector3) && typeof(Component).RTIsAssignableFrom(sourceType)) { return(() => { try { return (T)(object)((func() as Component).transform.position); } catch { return default(T); } }); } //from gameobject to Vector3 (position) if (targetType == typeof(Vector3) && sourceType == typeof(GameObject)) { return(() => { try { return (T)(object)((func() as GameObject).transform.position); } catch { return default(T); } }); } //from component to Quaternion (rotation) if (targetType == typeof(Quaternion) && typeof(Component).RTIsAssignableFrom(sourceType)) { return(() => { try { return (T)(object)((func() as Component).transform.rotation); } catch { return default(T); } }); } //from gameobject to Quaternion (rotation) if (targetType == typeof(Quaternion) && sourceType == typeof(GameObject)) { return(() => { try { return (T)(object)((func() as GameObject).transform.rotation); } catch { return default(T); } }); } ///---------------------------------------------------------------------------------------------- //from component to component if (typeof(Component).RTIsAssignableFrom(targetType) && typeof(Component).RTIsAssignableFrom(sourceType)) { return(() => { try { return (T)(object)((func() as Component).GetComponent(targetType)); } catch { return default(T); } }); } //from gameobject to component if (typeof(Component).RTIsAssignableFrom(targetType) && sourceType == typeof(GameObject)) { return(() => { try { return (T)(object)((func() as GameObject).GetComponent(targetType)); } catch { return default(T); } }); } //from component to gameobject if (targetType == typeof(GameObject) && typeof(Component).RTIsAssignableFrom(sourceType)) { return(() => { try { return (T)(object)((func() as Component).gameObject); } catch { return default(T); } }); } ///---------------------------------------------------------------------------------------------- //From IEnumerable to IEnumerable for Lists and Arrays if (typeof(IEnumerable).RTIsAssignableFrom(sourceType) && typeof(IEnumerable).RTIsAssignableFrom(targetType)) { try { var elementFrom = sourceType.RTIsArray()? sourceType.GetElementType() : sourceType.GetGenericArguments().Single(); var elementTo = targetType.RTIsArray()? targetType.GetElementType() : targetType.GetGenericArguments().Single(); if (elementTo.RTIsAssignableFrom(elementFrom)) { var listType = typeof(List <>).RTMakeGenericType(elementTo); return(() => { var list = (IList)System.Activator.CreateInstance(listType); foreach (var o in (IEnumerable)func()) { list.Add(o); } return (T)list; }); } } catch { return(null); } } return(null); }