/// <summary> /// Provides the implementation for operations that invoke an object. Classes derived from the <see cref="T:System.Dynamic.DynamicObject"/> class can override this method to specify dynamic behavior for operations such as invoking an object or a delegate. /// </summary> /// <param name="binder">Provides information about the invoke operation.</param> /// <param name="args">The arguments that are passed to the object during the invoke operation. For example, for the sampleObject(100) operation, where sampleObject is derived from the <see cref="T:System.Dynamic.DynamicObject"/> class, <paramref name="args[0]"/> is equal to 100.</param> /// <param name="result">The result of the object invocation.</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 TryInvoke(InvokeBinder binder, object[] args, out object result) { var tNamedArgs = Util.NameArgsIfNecessary(binder.CallInfo, args); var tNewArgs = _args.Concat(tNamedArgs).ToArray(); if (_totalArgCount.HasValue && (_totalArgCount - Args.Length - args.Length > 0)) //Not Done currying { result = new PartialApplyInvocation(Target, tNewArgs, MemberName, TotalArgCount, InvocationKind); return true; } var tInvokeDirect = String.IsNullOrWhiteSpace(_memberName); var tDel = _target as Delegate; if (tInvokeDirect && binder.CallInfo.ArgumentNames.Count == 0 && _target is Delegate) //Optimization for direct delegate calls { result = tDel.FastDynamicInvoke(tNewArgs); return true; } Invocation tInvocation; if (binder.CallInfo.ArgumentNames.Count == 0) //If no argument names we can cache the callsite { CacheableInvocation tCacheableInvocation; if (!_cacheableInvocation.TryGetValue(tNewArgs.Length, out tCacheableInvocation)) { tCacheableInvocation = new CacheableInvocation(InvocationKind, _memberName, argCount: tNewArgs.Length, context: _target); _cacheableInvocation[tNewArgs.Length] = tCacheableInvocation; } tInvocation = tCacheableInvocation; } else { tInvocation = new Invocation(InvocationKind, _memberName); } result = tInvocation.Invoke(_target, tNewArgs); return true; }
/// <summary> /// Equalses the specified other. /// </summary> /// <param name="other">The other.</param> /// <returns></returns> public bool Equals(Invocation other) { if (ReferenceEquals(null, other)) return false; if (ReferenceEquals(this, other)) return true; return Equals(other.Kind, Kind) && Equals(other.Name, Name) && (Equals(other.Args, Args) || Enumerable.SequenceEqual(other.Args, Args)); }