Beispiel #1
0
        /// <summary>
        /// プロパティ名から値を高速取得する
        /// </summary>
        /// <param name="obj">取得対象のオブジェクト</param>
        /// <param name="propertyName">プロパティ名</param>
        /// <returns>プロパティの値</returns>
        public static object GetPropertyValue(this object obj, string propertyName)
        {
            var type = obj.GetType();
            GetSiteCollection getSiteCollection = null;
            CallSite<Func<CallSite, object, object>> siteGet = null;

            //型キャッシュの存在確認
            if (_getSiteCollectionCache.TryGetValue(type, out getSiteCollection)) {
                siteGet = getSiteCollection[propertyName];

                //Getterキャッシュの存在確認
                if (siteGet != null) {
                    return siteGet.Target(siteGet, obj);
                }
            }

            var argInfo = new CSharpArgumentInfo[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null) };
            siteGet = CallSite<Func<CallSite, object, object>>.Create(Microsoft.CSharp.RuntimeBinder.Binder.GetMember(CSharpBinderFlags.None, propertyName, type, argInfo));

            if (getSiteCollection == null) {
                getSiteCollection = new GetSiteCollection(propertyName, siteGet);
                _getSiteCollectionCache.Add(type, getSiteCollection);
            } else {
                getSiteCollection.Add(propertyName, siteGet);
            }

            return siteGet.Target(siteGet, obj);
        }
        /// <summary>
        /// Reduces the dynamic expression to a binder and a set of arguments to apply the operation to.
        /// </summary>
        /// <param name="binder">The binder used to perform the dynamic operation.</param>
        /// <param name="arguments">The arguments to apply the dynamic operation to.</param>
        /// <param name="argumentTypes">The types of the arguments to use for the dynamic call site. Return null to infer types.</param>
        protected override void ReduceDynamic(out CallSiteBinder binder, out IEnumerable<Expression> arguments, out Type[] argumentTypes)
        {
            var n = Arguments.Count;

            var argumentInfos = new CSharpArgumentInfo[n + 1];
            var expressions = new Expression[n + 1];

            expressions[0] = Expression.Constant(Type, typeof(Type));
            argumentInfos[0] = CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.UseCompileTimeType | CSharpArgumentInfoFlags.IsStaticType, null);

            argumentTypes = null;
            CopyArguments(Arguments, argumentInfos, expressions, ref argumentTypes);

            binder = Binder.InvokeConstructor(Flags, Context, argumentInfos);
            arguments = expressions;
        }
        /// <summary>
        /// Reduces the dynamic expression to a binder and a set of arguments to apply the operation to.
        /// </summary>
        /// <param name="binder">The binder used to perform the dynamic operation.</param>
        /// <param name="arguments">The arguments to apply the dynamic operation to.</param>
        /// <param name="argumentTypes">The types of the arguments to use for the dynamic call site. Return null to infer types.</param>
        protected override void ReduceDynamic(out CallSiteBinder binder, out IEnumerable<Expression> arguments, out Type[] argumentTypes)
        {
            var n = Arguments.Count;

            var argumentInfos = new CSharpArgumentInfo[n + 1];
            var expressions = new Expression[n + 1];

            expressions[0] = Expression;
            argumentInfos[0] = CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null);

            argumentTypes = null;
            CopyArguments(Arguments, argumentInfos, expressions, ref argumentTypes);

            binder = Binder.Invoke(Flags, Context, argumentInfos);
            arguments = expressions;
        }
        /// <summary>
        /// Reduces the dynamic expression to a binder and a set of arguments to apply the operation to.
        /// </summary>
        /// <param name="binder">The binder used to perform the dynamic operation.</param>
        /// <param name="arguments">The arguments to apply the dynamic operation to.</param>
        /// <param name="argumentTypes">The types of the arguments to use for the dynamic call site. Return null to infer types.</param>
        protected override void ReduceDynamic(out CallSiteBinder binder, out IEnumerable<Expression> arguments, out Type[] argumentTypes)
        {
            var n = Arguments.Count;

            var argumentInfos = new CSharpArgumentInfo[n + 1];
            var expressions = new Expression[n + 1];

            // NB: By-ref passing for the receiver seems to be omitted in Roslyn here; see https://github.com/dotnet/roslyn/issues/6818.
            //     We're choosing to be consistent with that behavior until further notice.
            expressions[0] = Object;
            argumentInfos[0] = CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null);

            argumentTypes = null;
            CopyArguments(Arguments, argumentInfos, expressions, ref argumentTypes);

            binder = Binder.GetIndex(Flags, Context, argumentInfos);
            arguments = expressions;
        }
Beispiel #5
0
		//
		// Creates mcs expression from dynamic object
		//
		public Compiler.Expression CreateCompilerExpression (CSharpArgumentInfo info, DynamicMetaObject value)
		{
			//
			// No type details provider, go with runtime type
			//
			if (info == null) {
				if (value.LimitType == typeof (object))
					return new Compiler.NullLiteral (Compiler.Location.Null);

				return new Compiler.RuntimeValueExpression (value, ImportType (value.RuntimeType));
			}

			//
			// Value is known to be a type
			//
			if ((info.Flags & CSharpArgumentInfoFlags.IsStaticType) != 0)
				return new Compiler.TypeExpression (ImportType ((Type) value.Value), Compiler.Location.Null);

			if (value.Value == null &&
				(info.Flags & (CSharpArgumentInfoFlags.IsOut | CSharpArgumentInfoFlags.IsRef | CSharpArgumentInfoFlags.UseCompileTimeType)) == 0 &&
				value.LimitType == typeof (object)) {
				return new Compiler.NullLiteral (Compiler.Location.Null);
			}

			//
			// Use compilation time type when type was known not to be dynamic during compilation
			//
			Type value_type = (info.Flags & CSharpArgumentInfoFlags.UseCompileTimeType) != 0 ? value.Expression.Type : value.LimitType;
			var type = ImportType (value_type);

			if ((info.Flags & CSharpArgumentInfoFlags.Constant) != 0)
				return Compiler.Constant.CreateConstantFromValue (type, value.Value, Compiler.Location.Null);

			return new Compiler.RuntimeValueExpression (value, type);
		}
Beispiel #6
0
		//
		// Creates mcs expression from dynamic method object
		//
		public static Compiler.Expression CreateCompilerExpression (CSharpArgumentInfo info, DynamicMetaObject value)
		{
			if (value.Value == null) {
				if (value.LimitType == typeof (object))
					return new Compiler.NullLiteral (Compiler.Location.Null);

				InitializeCompiler (null);
				return Compiler.Constant.CreateConstantFromValue (TypeImporter.Import (value.LimitType), null, Compiler.Location.Null);
			}

			bool is_compile_time;

			if (info != null) {
				if ((info.Flags & CSharpArgumentInfoFlags.Constant) != 0) {
					InitializeCompiler (null);
					return Compiler.Constant.CreateConstantFromValue (TypeImporter.Import (value.LimitType), value.Value, Compiler.Location.Null);
				}

				if ((info.Flags & CSharpArgumentInfoFlags.IsStaticType) != 0)
					return new Compiler.TypeExpression (TypeImporter.Import ((Type) value.Value), Compiler.Location.Null);

				is_compile_time = (info.Flags & CSharpArgumentInfoFlags.UseCompileTimeType) != 0;
			} else {
				is_compile_time = false;
			}

			return new Compiler.RuntimeValueExpression (value, TypeImporter.Import (is_compile_time ? value.LimitType : value.RuntimeType));
		}
Beispiel #7
0
        public static void CopyArguments(ReadOnlyCollection<DynamicCSharpArgument> arguments, CSharpArgumentInfo[] argumentInfos, Expression[] expressions, ref Type[] argumentTypes)
        {
            var n = arguments.Count;

            for (var i = 0; i < n; i++)
            {
                var argument = arguments[i];
                argumentInfos[i + 1] = argument.ArgumentInfo;
                expressions[i + 1] = argument.Expression;

                if ((argument.Flags & (CSharpArgumentInfoFlags.IsRef | CSharpArgumentInfoFlags.IsOut)) != 0)
                {
                    if (argumentTypes == null)
                    {
                        argumentTypes = new Type[argumentInfos.Length];
                        argumentTypes[0] = expressions[0].Type;

                        for (var j = 0; j < i; j++)
                        {
                            argumentTypes[j + 1] = arguments[j].Expression.Type;
                        }
                    }

                    argumentTypes[i + 1] = argument.Expression.Type.MakeByRefType();
                }
                else if (argumentTypes != null)
                {
                    argumentTypes[i + 1] = argument.Expression.Type;
                }
            }
        }
Beispiel #8
0
        public static void CopyReceiverArgument(Expression receiver, CSharpArgumentInfo[] argumentInfos, Expression[] expressions, ref Type[] argumentTypes)
        {
            var receiverFlags = CSharpArgumentInfoFlags.None;
            if (IsReceiverByRef(receiver))
            {
                receiverFlags |= CSharpArgumentInfoFlags.IsRef;
                argumentTypes = new Type[argumentInfos.Length];
                argumentTypes[0] = receiver.Type.MakeByRefType();
            }

            expressions[0] = receiver;
            argumentInfos[0] = CSharpArgumentInfo.Create(receiverFlags, null);
        }
        protected override void ReduceDynamic(out CallSiteBinder binder, out IEnumerable<Expression> arguments, out Type[] argumentTypes)
        {
            var n = Arguments.Count;

            var argumentInfos = new CSharpArgumentInfo[n + 1];
            var expressions = new Expression[n + 1];

            argumentTypes = null;
            CopyReceiverArgument(Object, argumentInfos, expressions, ref argumentTypes);
            CopyArguments(Arguments, argumentInfos, expressions, ref argumentTypes);

            binder = Binder.InvokeMember(Flags, Name, TypeArguments, Context, argumentInfos);
            arguments = expressions;
        }
        private void ReduceAssignment(Expression value, CSharpBinderFlags flags, CSharpArgumentInfoFlags leftFlags, CSharpArgumentInfoFlags rightFlags, out CallSiteBinder binder, out IEnumerable<Expression> arguments, out Type[] argumentTypes)
        {
            var n = Arguments.Count;

            var argumentInfos = new CSharpArgumentInfo[n + 2];
            var expressions = new Expression[n + 2];

            // NB: By-ref passing for the receiver seems to be omitted in Roslyn here; see https://github.com/dotnet/roslyn/issues/6818.
            //     We're choosing to be consistent with that behavior until further notice.
            expressions[0] = Object;
            argumentInfos[0] = CSharpArgumentInfo.Create(leftFlags, null);

            argumentTypes = null;
            CopyArguments(Arguments, argumentInfos, expressions, ref argumentTypes);

            argumentInfos[n + 1] = CSharpArgumentInfo.Create(rightFlags, null); // TODO: check
            expressions[n + 1] = value;

            flags |= Flags;

            binder = Binder.SetMember(flags, Name, Context, argumentInfos);
            arguments = expressions;
        }
Beispiel #11
0
        /////////////////////////////////////////////////////////////////////////////////

        private static bool IsDynamicallyTypedRuntimeProxy(DynamicMetaObject argument, CSharpArgumentInfo info)
        {
            // This detects situations where, although the argument has a value with
            // a given type, that type is insufficient to determine, statically, the
            // set of reference conversions that are going to exist at bind time for
            // different values. For instance, one __ComObject may allow a conversion
            // to IFoo while another does not.

            bool isDynamicObject =
                info != null &&
                !info.UseCompileTimeType &&
                (IsComObject(argument.Value) || IsTransparentProxy(argument.Value));

            return(isDynamicObject);
        }
Beispiel #12
0
        internal static DynamicMetaObject Bind(
            DynamicMetaObjectBinder action,
            RuntimeBinder binder,
            DynamicMetaObject[] args,
            IEnumerable <CSharpArgumentInfo> arginfos,
            DynamicMetaObject onBindingError)
        {
            Expression[]        parameters   = new Expression[args.Length];
            BindingRestrictions restrictions = BindingRestrictions.Empty;
            ICSharpInvokeOrInvokeMemberBinder callPayload = action as ICSharpInvokeOrInvokeMemberBinder;
            ParameterExpression tempForIncrement          = null;
            IEnumerator <CSharpArgumentInfo> arginfosEnum = (arginfos ?? Array.Empty <CSharpArgumentInfo>()).GetEnumerator();

            for (int index = 0; index < args.Length; ++index)
            {
                DynamicMetaObject o = args[index];
                // Our contract with the DLR is such that we will not enter a bind unless we have
                // values for the meta-objects involved.

                if (!o.HasValue)
                {
                    Debug.Assert(false, "The runtime binder is being asked to bind a metaobject without a value");
                    throw Error.InternalCompilerError();
                }

                CSharpArgumentInfo info = arginfosEnum.MoveNext() ? arginfosEnum.Current : null;

                if (index == 0 && IsIncrementOrDecrementActionOnLocal(action))
                {
                    // We have an inc or a dec operation. Insert the temp local instead.
                    //
                    // We need to do this because for value types, the object will come
                    // in boxed, and we'd need to unbox it to get the original type in order
                    // to increment. The only way to do that is to create a new temporary.
                    object value = o.Value;
                    tempForIncrement = Expression.Variable(value != null ? value.GetType() : typeof(object), "t0");
                    parameters[0]    = tempForIncrement;
                }
                else
                {
                    parameters[index] = o.Expression;
                }

                BindingRestrictions r = DeduceArgumentRestriction(index, callPayload, o, info);
                restrictions = restrictions.Merge(r);

                // Here we check the argument info. If the argument info shows that the current argument
                // is a literal constant, then we also add an instance restriction on the value of
                // the constant.
                if (info != null && info.LiteralConstant)
                {
                    if (o.Value is double && double.IsNaN((double)o.Value))
                    {
                        MethodInfo isNaN = s_DoubleIsNaN ?? (s_DoubleIsNaN = typeof(double).GetMethod("IsNaN"));
                        Expression e     = Expression.Call(null, isNaN, o.Expression);
                        restrictions = restrictions.Merge(BindingRestrictions.GetExpressionRestriction(e));
                    }
                    else if (o.Value is float && float.IsNaN((float)o.Value))
                    {
                        MethodInfo isNaN = s_SingleIsNaN ?? (s_SingleIsNaN = typeof(float).GetMethod("IsNaN"));
                        Expression e     = Expression.Call(null, isNaN, o.Expression);
                        restrictions = restrictions.Merge(BindingRestrictions.GetExpressionRestriction(e));
                    }
                    else
                    {
                        Expression e = Expression.Equal(o.Expression, Expression.Constant(o.Value, o.Expression.Type));
                        r            = BindingRestrictions.GetExpressionRestriction(e);
                        restrictions = restrictions.Merge(r);
                    }
                }
            }

            // Get the bound expression.
            try
            {
                DynamicMetaObject deferredBinding;
                Expression        expression = binder.Bind(action, parameters, args, out deferredBinding);

                if (deferredBinding != null)
                {
                    expression   = ConvertResult(deferredBinding.Expression, action);
                    restrictions = deferredBinding.Restrictions.Merge(restrictions);
                    return(new DynamicMetaObject(expression, restrictions));
                }

                if (tempForIncrement != null)
                {
                    // If we have a ++ or -- payload, we need to do some temp rewriting.
                    // We rewrite to the following:
                    //
                    // temp = (type)o;
                    // temp++;
                    // o = temp;
                    // return o;

                    DynamicMetaObject arg0 = args[0];

                    expression = Expression.Block(
                        new[] { tempForIncrement },
                        Expression.Assign(tempForIncrement, Expression.Convert(arg0.Expression, arg0.Value.GetType())),
                        expression,
                        Expression.Assign(arg0.Expression, Expression.Convert(tempForIncrement, arg0.Expression.Type)));
                }

                expression = ConvertResult(expression, action);

                return(new DynamicMetaObject(expression, restrictions));
            }
            catch (RuntimeBinderException e)
            {
                if (onBindingError != null)
                {
                    return(onBindingError);
                }

                return(new DynamicMetaObject(
                           Expression.Throw(
                               Expression.New(
                                   typeof(RuntimeBinderException).GetConstructor(new Type[] { typeof(string) }),
                                   Expression.Constant(e.Message)
                                   ),
                               GetTypeForErrorMetaObject(action, args.Length == 0 ? null : args[0])
                               ),
                           restrictions
                           ));
            }
        }
Beispiel #13
0
        internal static DynamicMetaObject Bind(
            DynamicMetaObjectBinder action,
            RuntimeBinder binder,
            IEnumerable <DynamicMetaObject> args,
            IEnumerable <CSharpArgumentInfo> arginfos,
            DynamicMetaObject onBindingError)
        {
            List <Expression>   parameters   = new List <Expression>();
            BindingRestrictions restrictions = BindingRestrictions.Empty;
            ICSharpInvokeOrInvokeMemberBinder callPayload = action as ICSharpInvokeOrInvokeMemberBinder;
            ParameterExpression tempForIncrement          = null;
            IEnumerator <CSharpArgumentInfo> arginfosEnum = arginfos == null ? null : arginfos.GetEnumerator();

            int index = 0;

            foreach (DynamicMetaObject o in args)
            {
                // Our contract with the DLR is such that we will not enter a bind unless we have
                // values for the meta-objects involved.

                if (!o.HasValue)
                {
                    Debug.Assert(false, "The runtime binder is being asked to bind a metaobject without a value");
                    throw Error.InternalCompilerError();
                }
                CSharpArgumentInfo info = null;
                if (arginfosEnum != null && arginfosEnum.MoveNext())
                {
                    info = arginfosEnum.Current;
                }

                if (index == 0 && IsIncrementOrDecrementActionOnLocal(action))
                {
                    // We have an inc or a dec operation. Insert the temp local instead.
                    //
                    // We need to do this because for value types, the object will come
                    // in boxed, and we'd need to unbox it to get the original type in order
                    // to increment. The only way to do that is to create a new temporary.
                    tempForIncrement = Expression.Variable(o.Value != null ? o.Value.GetType() : typeof(object), "t0");
                    parameters.Add(tempForIncrement);
                }
                else
                {
                    parameters.Add(o.Expression);
                }

                BindingRestrictions r = DeduceArgumentRestriction(index, callPayload, o, info);
                restrictions = restrictions.Merge(r);

                // Here we check the argument info. If the argument info shows that the current argument
                // is a literal constant, then we also add an instance restriction on the value of
                // the constant.
                if (info != null && info.LiteralConstant)
                {
                    if ((o.Value is float && float.IsNaN((float)o.Value)) ||
                        o.Value is double && double.IsNaN((double)o.Value))
                    {
                        // We cannot create an equality restriction for NaN, because equality is implemented
                        // in such a way that NaN != NaN and the rule we make would be unsatisfiable.
                    }
                    else
                    {
                        Expression e = Expression.Equal(o.Expression, Expression.Constant(o.Value, o.Expression.Type));
                        r            = BindingRestrictions.GetExpressionRestriction(e);
                        restrictions = restrictions.Merge(r);
                    }
                }

                ++index;
            }

            // Get the bound expression.
            try
            {
                DynamicMetaObject deferredBinding;
                Expression        expression = binder.Bind(action, parameters, args.ToArray(), out deferredBinding);

                if (deferredBinding != null)
                {
                    expression   = ConvertResult(deferredBinding.Expression, action);
                    restrictions = deferredBinding.Restrictions.Merge(restrictions);
                    return(new DynamicMetaObject(expression, restrictions));
                }

                if (tempForIncrement != null)
                {
                    // If we have a ++ or -- payload, we need to do some temp rewriting.
                    // We rewrite to the following:
                    //
                    // temp = (type)o;
                    // temp++;
                    // o = temp;
                    // return o;

                    DynamicMetaObject arg0 = Enumerable.First(args);

                    Expression assignTemp = Expression.Assign(
                        tempForIncrement,
                        Expression.Convert(arg0.Expression, arg0.Value.GetType()));
                    Expression assignResult = Expression.Assign(
                        arg0.Expression,
                        Expression.Convert(tempForIncrement, arg0.Expression.Type));
                    List <Expression> expressions = new List <Expression>();

                    expressions.Add(assignTemp);
                    expressions.Add(expression);
                    expressions.Add(assignResult);

                    expression = Expression.Block(new ParameterExpression[] { tempForIncrement }, expressions);
                }

                expression = ConvertResult(expression, action);

                return(new DynamicMetaObject(expression, restrictions));
            }
            catch (RuntimeBinderException e)
            {
                if (onBindingError != null)
                {
                    return(onBindingError);
                }

                return(new DynamicMetaObject(
                           Expression.Throw(
                               Expression.New(
                                   typeof(RuntimeBinderException).GetConstructor(new Type[] { typeof(string) }),
                                   Expression.Constant(e.Message)
                                   ),
                               GetTypeForErrorMetaObject(action, args.FirstOrDefault())
                               ),
                           restrictions
                           ));
            }
        }
        private void ReduceAssignment(Expression value, CSharpBinderFlags flags, CSharpArgumentInfoFlags leftFlags, CSharpArgumentInfoFlags rightFlags, out CallSiteBinder binder, out IEnumerable<Expression> arguments, out Type[] argumentTypes)
        {
            var n = Arguments.Count;

            var argumentInfos = new CSharpArgumentInfo[n + 2];
            var expressions = new Expression[n + 2];

            // NB: This is the only place where by-ref passing for the receiver is done in Roslyn; for more
            //     info about the apparent inconsistency see https://github.com/dotnet/roslyn/issues/6818.
            //     We're choosing to be consistent with that behavior until further notice.
            if (IsReceiverByRef(Object))
            {
                leftFlags |= CSharpArgumentInfoFlags.IsRef;
            }

            expressions[0] = Object;
            argumentInfos[0] = CSharpArgumentInfo.Create(leftFlags, null);

            argumentTypes = null;
            CopyArguments(Arguments, argumentInfos, expressions, ref argumentTypes);

            argumentInfos[n + 1] = CSharpArgumentInfo.Create(rightFlags, null); // TODO: check
            expressions[n + 1] = value;

            flags |= Flags;

            binder = Binder.SetIndex(flags, Context, argumentInfos);
            arguments = expressions;
        }
Beispiel #15
0
 private static IEnumerable<CSharpArgumentInfo> GetBinderArguments(int count)
 {
     var arr = new CSharpArgumentInfo[count];
     for (int i = 0; i < count; i++)
     {
         arr[i] = CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.UseCompileTimeType, null);
     }
     return arr;
 }
		//
		// Creates mcs expression from dynamic method object
		//
		public static Compiler.Expression CreateCompilerExpression (CSharpArgumentInfo info, DynamicMetaObject value, bool typed)
		{
			if (info.IsNamed)
				throw new NotImplementedException ("IsNamed");

			if (value.Value == null)
				return new Compiler.NullLiteral (value.LimitType, Compiler.Location.Null);

			if ((info.Flags & CSharpArgumentInfoFlags.LiteralConstant) != 0) {
				if (!typed)
					throw new NotImplementedException ("weakly typed constant");

				return Compiler.Constant.CreateConstant (value.RuntimeType ?? value.LimitType, value.Value, Compiler.Location.Null);
			}

			return new Compiler.RuntimeValueExpression (value, typed);
		}
Beispiel #17
0
        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;
        }
        public static object TryEvalUnaryOperators <T>(T obj, ExpressionType oper, Type accessibilityContext)
        {
            if (oper == ExpressionType.IsTrue || oper == ExpressionType.IsFalse)
            {
                var trueFalseSite = CallSite <Func <CallSite, T, bool> >
                                    .Create(new Microsoft.CSharp.RuntimeBinder.CSharpUnaryOperationBinder(oper,
                                                                                                          false,
                                                                                                          accessibilityContext,
                                                                                                          new CSharpArgumentInfo[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null) }));

                return(trueFalseSite.Target(trueFalseSite, obj));
            }

            var site = CallSite <Func <CallSite, T, object> >
                       .Create(new Microsoft.CSharp.RuntimeBinder.CSharpUnaryOperationBinder(oper,
                                                                                             false,
                                                                                             accessibilityContext,
                                                                                             new CSharpArgumentInfo[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null) }));

            return(site.Target(site, obj));
        }