// /** // * File: Cast.cs // * Author: haraldwolff // * // * This file and it's content is copyrighted by the Author and / or copyright holder. // * Any use wihtout proper permission is illegal and may lead to legal actions. // * // * // **/ using System; using System.Reflection; using System.Linq; using System.Threading; using System.Net.Http.Headers; using System.ComponentModel; namespace ln.type { public static class Cast { public static T To(object value) => (T)To(value, typeof(T)); public static object To(object value, Type targetType) { if (!To(value, targetType, out object targetValue)) throw new NotSupportedException(); return targetValue; } public static bool To(object value, Type targetType, out object targetValue) { targetValue = null; if (Object.ReferenceEquals(null, value)) return true; if (targetType.IsInstanceOfType(value)) { targetValue = value; return true; } if ( !Implicit(value, targetType, out targetValue) && !Implicit(value, value.GetType(), targetType, out targetValue) && !Explicit(value, targetType, out targetValue) && !Explicit(value, value.GetType(), targetType, out targetValue) ) { if (targetType.IsEnum) { if (value is string sValue) { targetValue = Enum.Parse(targetType, sValue); } else { throw new NotSupportedException(); } } else if (targetType.IsArray) { Array array = value as Array; Array castedArray = Array.CreateInstance(targetType.GetElementType(), array.Length); for (int n = 0; n < array.Length; n++) { if (!To(array.GetValue(n), targetType.GetElementType(), out object el)) return false; castedArray.SetValue(el, n); } targetValue = castedArray; } else if ((value is string text) && (TypeDescriptor.GetConverter(targetType).CanConvertFrom(typeof(string)))) { targetValue = TypeDescriptor.GetConverter(targetType).ConvertFromInvariantString(value as string); } else { targetValue = Convert.ChangeType(value, targetType); } } return true; } public static bool Implicit(object value, Type type, out object casted) => Implicit(value, type, type, out casted); public static bool Implicit(object value, Type type, Type targetType, out object casted) { foreach (MethodInfo methodInfo in type.GetMethods(BindingFlags.Public | BindingFlags.Static)) { if (methodInfo.Name.Equals("op_Implicit") && methodInfo.ReturnType.Equals(targetType)) { ParameterInfo parameterInfo = methodInfo.GetParameters().FirstOrDefault(); if ((parameterInfo != null) && (parameterInfo.ParameterType.Equals(value.GetType()))) { casted = methodInfo.Invoke(null, new object[] { value }); return true; } } } casted = null; return false; } public static bool Explicit(object value, Type type, out object casted) => Implicit(value, type, type, out casted); public static bool Explicit(object value, Type type, Type targetType, out object casted) { foreach (MethodInfo methodInfo in type.GetMethods(BindingFlags.Public | BindingFlags.Static)) { if (methodInfo.Name.Equals("op_Explicit") && methodInfo.ReturnType.Equals(targetType)) { ParameterInfo parameterInfo = methodInfo.GetParameters().FirstOrDefault(); if ((parameterInfo != null) && (parameterInfo.ParameterType.Equals(value.GetType()))) { casted = methodInfo.Invoke(null, new object[] { value }); return true; } } } casted = null; return false; } } }