/// <summary> /// DynamicOperatorRewriter in EE generates call to this method to dynamically invoke a property getter /// with no arguments. /// </summary> /// <typeparam name="T">Type of object on which property is defined.</typeparam> /// <param name="obj">Object on which property is defined.</param> /// <param name="propName">Name of a property to invoke.</param> /// <param name="accessibilityContext">Type that determines context in which method should be called.</param> /// <param name="isResultIndexed">Determines if COM binder should return a callable object.</param> /// <returns>Result of property invocation.</returns> public static object TryGetMemberValue <T>(T obj, string propName, Type accessibilityContext, bool isResultIndexed) { // In most cases it's ok to use CSharpArgumentInfoFlags.None since target of property call is dynamic. // The only possible case when target is not dynamic but we still treat is as dynamic access is when // one of arguments is dynamic. This is only possible for indexed properties since we call this method and // TryGetMemberValueVarArgs afterwards. CSharpGetMemberBinder binder = new CSharpGetMemberBinder( propName, isResultIndexed, accessibilityContext, new CSharpArgumentInfo[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null) }); var site = CallSite <Func <CallSite, T, object> > .Create(binder); return(site.Target(site, obj)); }
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; }