public override DynamicMetaObject FallbackInvoke( DynamicMetaObject targetMO, DynamicMetaObject[] argMOs, DynamicMetaObject errorSuggestion) { // First try COM binding. DynamicMetaObject result; if (ComBinder.TryBindInvoke(this, targetMO, argMOs, out result)) { return result; } // Defer if any object has no value so that we evaulate their // Expressions and nest a CallSite for the InvokeMember. if (!targetMO.HasValue || argMOs.Any((a) => !a.HasValue)) { var deferArgs = new DynamicMetaObject[argMOs.Length + 1]; for (int i = 0; i < argMOs.Length; i++) { deferArgs[i + 1] = argMOs[i]; } deferArgs[0] = targetMO; return Defer(deferArgs); } //Find our own binding. if (targetMO.LimitType.IsSubclassOf(typeof(Delegate))) { var parms = targetMO.LimitType.GetMethod("Invoke").GetParameters(); if (parms.Length == argMOs.Length) { // Don't need to check if argument types match parameters. // If they don't, users get an argument conversion error. var callArgs = RuntimeHelpers.ConvertArguments(argMOs, parms); var expression = Expression.Invoke( Expression.Convert(targetMO.Expression, targetMO.LimitType), callArgs); return new DynamicMetaObject( RuntimeHelpers.EnsureObjectResult(expression), BindingRestrictions.GetTypeRestriction(targetMO.Expression, targetMO.LimitType)); } } return errorSuggestion ?? RuntimeHelpers.CreateThrow( targetMO, argMOs, BindingRestrictions.GetTypeRestriction(targetMO.Expression, targetMO.LimitType), typeof(InvalidOperationException), "Wrong number of arguments for function -- " + targetMO.LimitType.ToString() + " got " + argMOs.ToString()); }
public override DynamicMetaObject FallbackInvokeMember( DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject errorSuggestion) { // First try COM binding. DynamicMetaObject result; if (ComBinder.TryBindInvokeMember(this, target, args, out result)) return result; // Defer if any object has no value so that we evaulate their // Expressions and nest a CallSite for the InvokeMember. if (!target.HasValue || args.Any((a) => !a.HasValue)) { var deferArgs = new DynamicMetaObject[args.Length + 1]; for (int i = 0; i < args.Length; i++) { deferArgs[i + 1] = args[i]; } deferArgs[0] = target; return Defer(deferArgs); } Func<DynamicMetaObject> getMethodNotFoundDMO = () => errorSuggestion ?? RuntimeHelpers.CreateThrow(target, args, RuntimeHelpers.GetTargetArgsRestrictions(target, args, false), typeof(MissingMethodException), String.Format(RuntimeMessages.PublicMethodDoesNotExist_Method_Type, this.Name, target.Value.GetType())); if (target.Value is HappyTypeTracker) { HappyTypeTracker typeTracker = (HappyTypeTracker) target.Value; IHappyTracker found; if (typeTracker.FindMemberTracker(this.Name, out found)) { HappyMethodTracker tracker = found as HappyMethodTracker; if(tracker == null) { return errorSuggestion ?? RuntimeHelpers.CreateThrow( target, args, RuntimeHelpers.GetTargetArgsRestrictions(target, args, false), typeof(MissingMemberException), String.Format(RuntimeMessages.MemberIsNotInvokable_MemberNameTypeName, found.Name, typeTracker.Name), args.ToString()); } return ResolveOverload(null, args, tracker.Methods, BindingRestrictions.GetInstanceRestriction(target.Expression, typeTracker)); } return getMethodNotFoundDMO(); } MethodInfo[] methods = target.Value.GetType().GetMethods(BindingFlags.Instance | BindingFlags.Public).Where(m => m.Name == Name).ToArray(); if(methods.Length != 0) return this.ResolveOverload(target, args, methods); return getMethodNotFoundDMO(); }
public override DynamicMetaObject FallbackInvokeMember( DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject errorSuggestion) { if (!target.HasValue || args.Any((a) => !a.HasValue)) { var deferArgs = new DynamicMetaObject[args.Length + 1]; for (var i = 0; i < args.Length; i++) deferArgs[i + 1] = args[i]; deferArgs[0] = target; return Defer(deferArgs); } // Find our own binding. // Could consider allowing invoking static members from an instance. const BindingFlags flags = BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Public; var members = target.LimitType.GetMember(Name, flags); if ((members.Length == 1) && (members[0] is PropertyInfo || members[0] is FieldInfo)) { // NEED TO TEST, should check for delegate value too var mem = members[0]; throw new NotImplementedException(); //return new DynamicMetaObject( // Expression.Dynamic( // new SymplInvokeBinder(new CallInfo(args.Length)), // typeof(object), // args.Select(a => a.Expression).AddFirst( // Expression.MakeMemberAccess(this.Expression, mem))); // Don't test for eventinfos since we do nothing with them now. } else { // Get MethodInfos with right arg counts. var methodInfos = members. Select(m => m as MethodInfo). Where(m => m.GetParameters().Length == args.Length); // Get MethodInfos with param types that work for args. This works // except for value args that need to pass to reftype params. // We could detect that to be smarter and then explicitly StrongBox // the args. var res = new List<MethodInfo>(); foreach (var mem in methodInfos) { if (RuntimeHelper.ParametersMatchArguments(mem.GetParameters(), args)) res.Add(mem); } // False below means generate a type restriction on the MO. // We are looking at the members target's Type. var restrictions = RuntimeHelper.GetTargetArgsRestrictions( target, args, false); if (res.Count == 0) { return errorSuggestion ?? RuntimeHelper.CreateThrow( target, args, restrictions, typeof (MissingMemberException), "Can't bind member invoke -- " + args.ToString()); } // Could have tried just letting Expr.Call factory do the work, // but if there is more than one applicable method using just // assignablefrom, Expr.Call throws. It does not pick a "most // applicable" method or any method. var callArgs = new Expression[0]; return new DynamicMetaObject( RuntimeHelper.EnsureObjectResult( Expression.Call( Expression.Convert(target.Expression, target.LimitType), res[0], callArgs)), restrictions); } }