/// <summary> /// Provides implementation for type conversion operations. Classes derived from the <see cref="T:System.Dynamic.DynamicObject"/> class can override this method to specify dynamic behavior for operations that convert an object from one type to another. /// </summary> /// <param name="binder">Provides information about the conversion operation. The binder.Type property provides the type to which the object must be converted. For example, for the statement (String)sampleObject in C# (CType(sampleObject, Type) in Visual Basic), where sampleObject is an instance of the class derived from the <see cref="T:System.Dynamic.DynamicObject"/> class, binder.Type returns the <see cref="T:System.String"/> type. The binder.Explicit property provides information about the kind of conversion that occurs. It returns true for explicit conversion and false for implicit conversion.</param> /// <param name="result">The result of the type conversion operation.</param> /// <returns> /// true if the operation is successful; otherwise, false. If this method returns false, the run-time binder of the language determines the behavior. (In most cases, a language-specific run-time exception is thrown.) /// </returns> public override bool TryConvert(ConvertBinder binder, out object result) { result = Dynamic.CoerceToDelegate(this, binder.Type); return(result != null); }
/// <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) { if (target != null && !type.IsInstanceOfType(target) && !IsDBNull(target)) { var delegateConversion = CoerceToDelegate(target, type); if (delegateConversion != null) { return(delegateConversion); } if (type.IsInterface && Impromptu.IsAvailable) { if (target is IDictionary <string, object> && !(target is DynamicObjects.BaseObject)) { target = new DynamicObjects.Dictionary((IDictionary <string, object>)target); } else if (!(target is DynamicObjects.BaseObject)) { target = new DynamicObjects.Get(target); } target = Impromptu.DynamicActLike(target, type); } else { try { object tResult; tResult = Dynamic.InvokeConvert(target, type, @explicit: true); target = tResult; } catch (RuntimeBinderException) { Type tReducedType = type; if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable <>)) { tReducedType = type.GetGenericArguments().First(); } if (typeof(Enum).IsAssignableFrom(tReducedType) && target is string) { target = Enum.Parse(tReducedType, target as String, true); } else if (target is IConvertible && typeof(IConvertible).IsAssignableFrom(tReducedType)) { target = Convert.ChangeType(target, tReducedType, Thread.CurrentThread.CurrentCulture); } else { try { dynamic converter = null; if (TypeDescriptor.IsAvailable) { converter = TypeDescriptor.GetConverter(tReducedType); } else if (TypeConverterAttributeSL != null) { var tAttributes = tReducedType.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) { } } } } } else if (((target == null) || IsDBNull(target)) && type.IsValueType) { target = Dynamic.InvokeConstructor(type); } else if (!type.IsInstanceOfType(target) && IsDBNull(target)) { return(null); } return(target); }
/// <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> /// <exception cref="System.ArgumentException">CacheableInvocation can't change conversion type on invoke.;args</exception> /// <exception cref="System.InvalidOperationException">Unknown Invocation Kind: </exception> public override object Invoke(object target, params object[] args) { var tIContext = target as InvokeContext; if (tIContext != null) { target = tIContext.Target; } if (args == null) { args = new object[] { null }; } if (args.Length != _argCount) { switch (Kind) { case InvocationKind.Convert: if (args.Length > 0) { if (!Equals(args[0], _convertType)) { throw new ArgumentException("CacheableInvocation can't change conversion type on invoke.", "args"); } } if (args.Length > 1) { if (!Equals(args[1], _convertExplicit)) { throw new ArgumentException("CacheableInvocation can't change explict/implict conversion on invoke.", "args"); } } if (args.Length > 2) { goto default; } break; default: throw new ArgumentException("args", string.Format("Incorrect number of Arguments for CachedInvocation, Expected:{0}", _argCount)); } } switch (Kind) { case InvocationKind.Constructor: var tTarget = (Type)target; return(InvokeHelper.InvokeConstructorCallSite(tTarget, tTarget.IsValueType, args, _argNames, ref _callSite)); case InvocationKind.Convert: return(InvokeHelper.InvokeConvertCallSite(target, _convertExplicit, _convertType, _context, ref _callSite)); case InvocationKind.Get: return(InvokeHelper.InvokeGetCallSite(target, Name.Name, _context, _staticContext, ref _callSite)); case InvocationKind.Set: InvokeHelper.InvokeSetCallSite(target, Name.Name, args[0], _context, _staticContext, ref _callSite); return(null); case InvocationKind.GetIndex: return(InvokeHelper.InvokeGetIndexCallSite(target, args, _argNames, _context, _staticContext, ref _callSite)); case InvocationKind.SetIndex: Dynamic.InvokeSetIndex(target, args); return(null); case InvocationKind.InvokeMember: return(InvokeHelper.InvokeMemberCallSite(target, (InvokeMemberName)Name, args, _argNames, _context, _staticContext, ref _callSite)); case InvocationKind.InvokeMemberAction: InvokeHelper.InvokeMemberActionCallSite(target, (InvokeMemberName)Name, args, _argNames, _context, _staticContext, ref _callSite); return(null); case InvocationKind.InvokeMemberUnknown: { try { var tObj = InvokeHelper.InvokeMemberCallSite(target, (InvokeMemberName)Name, args, _argNames, _context, _staticContext, ref _callSite); return(tObj); } catch (RuntimeBinderException) { InvokeHelper.InvokeMemberActionCallSite(target, (InvokeMemberName)Name, args, _argNames, _context, _staticContext, ref _callSite2); return(null); } } case InvocationKind.Invoke: return(InvokeHelper.InvokeDirectCallSite(target, args, _argNames, _context, _staticContext, ref _callSite)); case InvocationKind.InvokeAction: InvokeHelper.InvokeDirectActionCallSite(target, args, _argNames, _context, _staticContext, ref _callSite); return(null); case InvocationKind.InvokeUnknown: { try { var tObj = InvokeHelper.InvokeDirectCallSite(target, args, _argNames, _context, _staticContext, ref _callSite); return(tObj); } catch (RuntimeBinderException) { InvokeHelper.InvokeDirectActionCallSite(target, args, _argNames, _context, _staticContext, ref _callSite2); return(null); } } case InvocationKind.AddAssign: InvokeHelper.InvokeAddAssignCallSite(target, Name.Name, args, _argNames, _context, _staticContext, ref _callSite, ref _callSite2, ref _callSite3, ref _callSite4); return(null); case InvocationKind.SubtractAssign: InvokeHelper.InvokeSubtractAssignCallSite(target, Name.Name, args, _argNames, _context, _staticContext, ref _callSite, ref _callSite2, ref _callSite3, ref _callSite4); return(null); case InvocationKind.IsEvent: return(InvokeHelper.InvokeIsEventCallSite(target, Name.Name, _context, ref _callSite)); default: throw new InvalidOperationException("Unknown Invocation Kind: " + Kind); } }