protected override MethodBase[] ResolveMethods(CallSiteContext bound) { // check bound.TargetType is assignable from bound.TargetInstance if (bound.TargetType == null || bound.CurrentTargetInstance == null || bound.TargetType.Type.IsAssignableFrom(bound.CurrentTargetInstance.GetType()) == false) { // target instance cannot be used bound.TargetInstance = null; } // if (bound.Name != null) { // candidates: IEnumerable <MethodBase> candidates = bound.TargetType .SelectRuntimeMethods(bound.Name, bound.ClassContext) .SelectVisible(bound.ClassContext); if (bound.TargetInstance == null) { candidates = candidates.SelectStatic(); } // return(candidates.Construct(bound.TypeArguments).ToArray()); } else { throw new ArgumentException(); } }
protected override Expression BindMissingMethod(CallSiteContext bound) { var type = bound.TargetType; if (type == null) // already reported - class cannot be found { return(ConvertExpression.BindDefault(this.ReturnType)); } if (bound.TargetInstance != null && bound.CurrentTargetInstance != null) // it has been checked it is a subclass of TargetType { // ensure current scope's __call() is favoured over the specified class type = bound.CurrentTargetInstance.GetPhpTypeInfo(); } // try to find __call() first if we have $this var call = (bound.TargetInstance != null) ? BinderHelpers.FindMagicMethod(type, TypeMethods.MagicMethods.__call) : null; if (call == null) { // look for __callStatic() call = BinderHelpers.FindMagicMethod(type, TypeMethods.MagicMethods.__callstatic); } if (call != null) { Expression[] call_args; var name_expr = (_name != null) ? Expression.Constant(_name) : bound.IndirectName; if (call.Methods.All(IsClrMagicCallWithParams)) { // Template: target.__call(name, arg1, arg2, ...) // flatterns the arguments: call_args = ArrayUtils.AppendRange(name_expr, bound.Arguments); } else { // Template: target.__call(name, array) // regular PHP behavior: call_args = new Expression[] { name_expr, BinderHelpers.NewPhpArray(bound.Arguments, bound.Context, bound.ClassContext), }; } return(OverloadBinder.BindOverloadCall(_returnType, bound.TargetInstance, call.Methods, bound.Context, call_args, isStaticCallSyntax: true, lateStaticType: bound.TargetType, classContext: bound.ClassContext)); } // return(base.BindMissingMethod(bound)); }