/// <summary> /// Invokes the invocation on specified target with specific args. /// </summary> /// <param name="target">The target.</param> /// <param name="args">The args.</param> /// <returns></returns> public virtual object Invoke(object target, params object[] args) { switch (this.Kind) { case InvocationKind.Constructor: return(Dynamic.InvokeConstructor((Type)target, args)); case InvocationKind.Convert: bool tExplicit = false; if (this.Args.Length == 2) { tExplicit = (bool)args[1]; } return(Dynamic.InvokeConvert(target, (Type)args[0], tExplicit)); case InvocationKind.Get: return(Dynamic.InvokeGet(target, this.Name.Name)); case InvocationKind.Set: Dynamic.InvokeSet(target, this.Name.Name, args.FirstOrDefault()); return(null); case InvocationKind.GetIndex: return(Dynamic.InvokeGetIndex(target, args)); case InvocationKind.SetIndex: Dynamic.InvokeSetIndex(target, args); return(null); case InvocationKind.InvokeMember: return(Dynamic.InvokeMember(target, this.Name, args)); case InvocationKind.InvokeMemberAction: Dynamic.InvokeMemberAction(target, this.Name, args); return(null); case InvocationKind.InvokeMemberUnknown: { try { return(Dynamic.InvokeMember(target, this.Name, args)); } catch (RuntimeBinderException) { Dynamic.InvokeMemberAction(target, this.Name, args); return(null); } } case InvocationKind.Invoke: return(Dynamic.Invoke(target, args)); case InvocationKind.InvokeAction: Dynamic.InvokeAction(target, args); return(null); case InvocationKind.InvokeUnknown: { try { return(Dynamic.Invoke(target, args)); } catch (RuntimeBinderException) { Dynamic.InvokeAction(target, args); return(null); } } case InvocationKind.AddAssign: Dynamic.InvokeAddAssignMember(target, this.Name.Name, args.FirstOrDefault()); return(null); case InvocationKind.SubtractAssign: Dynamic.InvokeSubtractAssignMember(target, this.Name.Name, args.FirstOrDefault()); return(null); case InvocationKind.IsEvent: return(Dynamic.InvokeIsEvent(target, this.Name.Name)); default: throw new InvalidOperationException("Unknown Invocation Kind: " + this.Kind); } }
/// <summary> /// Goes the extra mile to convert target to type. /// </summary> /// <param name="target">The target.</param> /// <param name="type">The type.</param> /// <returns></returns> public static dynamic CoerceConvert(object target, Type type) { var typeInfo = type.GetTypeInfo(); if (target != null && !typeInfo.IsInstanceOfType(target) && !IsDBNull(target)) { var delegateConversion = CoerceToDelegate(target, type); if (delegateConversion != null) { return(delegateConversion); } if (typeInfo.IsInterface && Impromptu.IsAvailable) { if (target is IDictionary <string, object> tDict && !(tDict is DynamicObjects.BaseObject)) { target = new DynamicObjects.Dictionary(tDict); } else if (!(target is DynamicObjects.BaseObject)) { target = new DynamicObjects.Get(target); } target = Impromptu.DynamicActLike(target, type); } else { try { object tResult = Dynamic.InvokeConvert(target, type, @explicit: true); target = tResult; } catch (RuntimeBinderException) { Type tReducedType = type; if (typeInfo.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable <>)) { tReducedType = typeInfo.GetGenericArguments().First(); } if (typeof(Enum).GetTypeInfo().IsAssignableFrom(tReducedType) && target is string sVal) { target = Enum.Parse(tReducedType, sVal, true); } else if (target is IConvertible && typeof(IConvertible).GetTypeInfo().IsAssignableFrom(tReducedType)) { target = Convert.ChangeType(target, tReducedType, Net40.GetDefaultThreadCurrentCulture()); } else { try { dynamic converter = null; if (TypeDescriptor.IsAvailable) { converter = TypeDescriptor.GetConverter(tReducedType); } else if (TypeConverterAttributeSL != null) { var tAttributes = tReducedType.GetTypeInfo().GetCustomAttributes(TypeConverterAttributeSL, false); dynamic attribute = tAttributes.FirstOrDefault(); if (attribute != null) { converter = Impromptu.InvokeConstructor(Type.GetType(attribute.ConverterTypeName)); } } if (converter != null && converter.CanConvertFrom(target.GetType())) { target = converter.ConvertFrom(target); } } catch (RuntimeBinderException) { //This runtime converter block is a hail mary //lgtm [cs/empty-catch-block] } } } } }