/// <summary> /// This method binds rules for PhpMethod /// </summary> private void InvokePhpMethod(DynamicMetaObject/*!*/ target, DynamicMetaObject[]/*!!*/ args, /*object targetObj,*/ PhpRoutine/*!*/ routine, out BindingRestrictions restrictions, out Expression invokeMethodExpr) { Debug.Assert(target != null && target.Value != null); Debug.Assert(!(target.Value is IClrValue), "PhpRoutine should not be declared on CLR value type!"); /*if (target.Value is PhpObject) { // Restriction: typeof(target) == |target.TypeDesc.RealType| var targetPhpObj = (PhpObject)target.Value; Debug.Assert(targetPhpObj.TypeDesc.RealType == target.LimitType); Debug.Assert(target.Value.GetType() == target.LimitType); restrictions = BindingRestrictions.GetTypeRestriction(target.Expression, targetPhpObj.TypeDesc.RealType); } else*/ Debug.Assert(typeof(ClrObject).IsSealed); // just to ensure following condition is correct if (target.Value.GetType() == typeof(ClrObject)) { target = new ClrDynamicMetaObject(target); // unwrap the real object, get restrictions restrictions = target.Restrictions; } else { Debug.Assert(target.Value.GetType() == target.LimitType); // just for sure Debug.Assert(!(target.Value is PhpObject) || ((PhpObject)target.Value).TypeDesc.RealType == target.LimitType); restrictions = BindingRestrictions.GetTypeRestriction(target.Expression, target.LimitType); } BindingRestrictions argumentsRestrictions; Expression[] arguments; if (routine.Name != Name.SpecialMethodNames.Call) { args = GetArgumentsRange(args, 0, RealMethodArgumentCount);// This can't be done when _call method is invoked //Check if method has ArgAware attribute if ((routine.Properties & RoutineProperties.IsArgsAware) != 0 || routine.IsStatic)// this is because of hack in PHP.Library.XML library static methods that can be also called like instance methods { DynamicMetaObject scriptContext = args[0]; //Select arguments without scriptContext DynamicMetaObject[] realArgs = GetArgumentsRange(args, 1, RealMethodArgumentCount - 1); InvokeArgLess(target, scriptContext, routine.RoutineDesc, realArgs, out argumentsRestrictions, out invokeMethodExpr); restrictions = restrictions.Merge(argumentsRestrictions); return; } arguments = routine.PrepareArguments(args, _genericParamsCount, _paramsCount, out argumentsRestrictions); restrictions = restrictions.Merge(argumentsRestrictions); } else { arguments = BinderHelper.PackToExpressions(args); } //((PhpObject)target)) var realObjEx = Expression.Convert(target.Expression, routine.ArgFullInfo.DeclaringType);//targetObj.TypeDesc.RealType); //ArgFull( ((PhpObject)target), ScriptContext, args, ... ) invokeMethodExpr = Expression.Call(BinderHelper.WrapInstanceMethodCall(routine.ArgFullInfo), BinderHelper.CombineArguments(realObjEx, arguments)); invokeMethodExpr = ReturnArgumentHelpers.ReturnValueConversion(routine.ArgFullInfo, invokeMethodExpr); invokeMethodExpr = HandleResult(invokeMethodExpr, routine.ArgFullInfo.ReturnType, false); }
/// <summary> /// This method binds rules for PhpMethod /// </summary> private void InvokePhpMethod(DynamicMetaObject /*!*/ target, DynamicMetaObject[] /*!!*/ args, /*object targetObj,*/ PhpRoutine /*!*/ routine, out BindingRestrictions restrictions, out Expression invokeMethodExpr) { Debug.Assert(target != null && target.Value != null); Debug.Assert(!(target.Value is IClrValue), "PhpRoutine should not be declared on CLR value type!"); /*if (target.Value is PhpObject) * { * // Restriction: typeof(target) == |target.TypeDesc.RealType| * var targetPhpObj = (PhpObject)target.Value; * Debug.Assert(targetPhpObj.TypeDesc.RealType == target.LimitType); * Debug.Assert(target.Value.GetType() == target.LimitType); * restrictions = BindingRestrictions.GetTypeRestriction(target.Expression, targetPhpObj.TypeDesc.RealType); * } * else*/ Debug.Assert(typeof(ClrObject).IsSealed); // just to ensure following condition is correct if (target.Value.GetType() == typeof(ClrObject)) { target = new ClrDynamicMetaObject(target); // unwrap the real object, get restrictions restrictions = target.Restrictions; } else { Debug.Assert(target.Value.GetType() == target.LimitType); // just for sure Debug.Assert(!(target.Value is PhpObject) || ((PhpObject)target.Value).TypeDesc.RealType == target.LimitType); restrictions = BindingRestrictions.GetTypeRestriction(target.Expression, target.LimitType); } BindingRestrictions argumentsRestrictions; Expression[] arguments; if (routine.Name != PHP.Core.Reflection.DObject.SpecialMethodNames.Call) { args = GetArgumentsRange(args, 0, RealMethodArgumentCount);// This can't be done when _call method is invoked //Check if method has ArgAware attribute if ((routine.Properties & RoutineProperties.IsArgsAware) != 0 || routine.IsStatic)// this is because of hack in PHP.Library.XML library static methods that can be also called like instance methods { DynamicMetaObject scriptContext = args[0]; //Select arguments without scriptContext DynamicMetaObject[] realArgs = GetArgumentsRange(args, 1, RealMethodArgumentCount - 1); InvokeArgLess(target, scriptContext, routine.RoutineDesc, realArgs, out argumentsRestrictions, out invokeMethodExpr); restrictions = restrictions.Merge(argumentsRestrictions); return; } arguments = routine.PrepareArguments(args, _genericParamsCount, _paramsCount, out argumentsRestrictions); restrictions = restrictions.Merge(argumentsRestrictions); } else { arguments = BinderHelper.PackToExpressions(args); } //((PhpObject)target)) var realObjEx = Expression.Convert(target.Expression, routine.ArgFullInfo.DeclaringType);//targetObj.TypeDesc.RealType); //ArgFull( ((PhpObject)target), ScriptContext, args, ... ) invokeMethodExpr = Expression.Call(BinderHelper.WrapInstanceMethodCall(routine.ArgFullInfo), BinderHelper.CombineArguments(realObjEx, arguments)); invokeMethodExpr = ReturnArgumentHelpers.ReturnValueConversion(routine.ArgFullInfo, invokeMethodExpr); invokeMethodExpr = HandleResult(invokeMethodExpr, routine.ArgFullInfo.ReturnType, false); }