private bool DeferBinding(
DynamicMetaObjectBinder payload,
ArgumentObject[] arguments,
DynamicMetaObject[] args,
Dictionary<int, LocalVariableSymbol> dictionary,
out DynamicMetaObject deferredBinding)
{
// This method deals with any deferrals we need to do. We check deferrals up front
// and bail early if we need to do them.
// (1) InvokeMember deferral.
//
// This is the deferral for the d.Foo() scenario where Foo actually binds to a
// field or property, and not a method group that is invocable. We defer to
// the standard GetMember/Invoke pattern.
if (payload is CSharpInvokeMemberBinder)
{
ICSharpInvokeOrInvokeMemberBinder callPayload = payload as ICSharpInvokeOrInvokeMemberBinder;
int arity = callPayload.TypeArguments != null ? callPayload.TypeArguments.Count : 0;
MemberLookup mem = new MemberLookup();
EXPR callingObject = CreateCallingObjectForCall(callPayload, arguments, dictionary);
Debug.Assert(_bindingContext.ContextForMemberLookup() != null);
SymWithType swt = _symbolTable.LookupMember(
callPayload.Name,
callingObject,
_bindingContext.ContextForMemberLookup(),
arity,
mem,
(callPayload.Flags & CSharpCallFlags.EventHookup) != 0,
true);
if (swt != null && swt.Sym.getKind() != SYMKIND.SK_MethodSymbol)
{
// The GetMember only has one argument, and we need to just take the first arg info.
CSharpGetMemberBinder getMember = new CSharpGetMemberBinder(callPayload.Name, false, callPayload.CallingContext, new CSharpArgumentInfo[] { callPayload.ArgumentInfo[0] });
// The Invoke has the remaining argument infos. However, we need to redo the first one
// to correspond to the GetMember result.
CSharpArgumentInfo[] argInfos = new CSharpArgumentInfo[callPayload.ArgumentInfo.Count];
callPayload.ArgumentInfo.CopyTo(argInfos, 0);
argInfos[0] = CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null);
CSharpInvokeBinder invoke = new CSharpInvokeBinder(callPayload.Flags, callPayload.CallingContext, argInfos);
DynamicMetaObject[] newArgs = new DynamicMetaObject[args.Length - 1];
Array.Copy(args, 1, newArgs, 0, args.Length - 1);
deferredBinding = invoke.Defer(getMember.Defer(args[0]), newArgs);
return true;
}
}
deferredBinding = null;
return false;
}