Exemple #1
0
 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);
            }
        }