public override DynamicMetaObject FallbackGetMember(DynamicMetaObject target, DynamicMetaObject?errorSuggestion)
        {
            // First try COM binding.
            if (ComBinder.TryBindGetMember(this, target, out var result, true))
            {
                return(result);
            }

            // Defer if any object has no value so that we evaluate their Expressions and nest a
            // CallSite for the InvokeMember.
            if (!target.HasValue)
            {
                return(Defer(target));
            }

            // Find our own binding.
            var members = target.LimitType.GetMember(Name, BindingFlags.IgnoreCase | BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public);

            return(members.Length == 1
                ? new DynamicMetaObject(
                       RuntimeHelpers.EnsureObjectResult(Expression.MakeMemberAccess(
                                                             Expression.Convert(target.Expression, members[0].DeclaringType !), members[0])),
                       // Don't need restriction test for name since this rule is only used where binder
                       // is used, which is only used in sites with this binder.Name.
                       BindingRestrictions.GetTypeRestriction(target.Expression, target.LimitType))
                : errorSuggestion ?? RuntimeHelpers.CreateThrow(target, null,
                                                                BindingRestrictions.GetTypeRestriction(target.Expression, target.LimitType),
                                                                typeof(MissingMemberException), $"cannot bind member, {Name}, on object {target.Value}"));
        }
示例#2
0
        public override DynamicMetaObject FallbackSetMember(DynamicMetaObject target, DynamicMetaObject value, DynamicMetaObject errorSuggestion)
        {
            if (ComBinder.TryBindSetMember(this, target, value, out DynamicMetaObject result))
            {
                return(result);
            }

            if (!target.HasValue)
            {
                return(Defer(target));
            }

            var flags   = BindingFlags.Instance | BindingFlags.Public | BindingFlags.Static;
            var members = target.LimitType.GetMember(Name, flags);

            if (members.Length == 1)
            {
                var        member = members[0];
                Expression val;

                switch (member.MemberType)
                {
                case MemberTypes.Property:
                    val = Expression.Convert(value.Expression, ((PropertyInfo)member).PropertyType);
                    break;

                case MemberTypes.Field:
                    val = Expression.Convert(value.Expression, ((FieldInfo)member).FieldType);
                    break;

                default:
                {
                    var error = new string[] { "Only property and field setting is supported!" };

                    return(errorSuggestion ??
                           RuntimeHelpers.CreateThrow(target, null,
                                                      BindingRestrictions.GetTypeRestriction(target.Expression, target.LimitType),
                                                      typeof(InvalidOperationException), error));
                }
                }

                return(new DynamicMetaObject(
                           RuntimeHelpers.EnsureObjectResult(
                               Expression.Assign(
                                   Expression.MakeMemberAccess(
                                       Expression.Convert(target.Expression, members[0].DeclaringType),
                                       members[0]),
                                   val)),
                           BindingRestrictions.GetTypeRestriction(target.Expression, target.LimitType)));
            }
            else
            {
                var error = new string[] { $"\"{target.RuntimeType}\" contains {members.Length} definitions of \"{Name}\"!" };

                return(errorSuggestion ??
                       RuntimeHelpers.CreateThrow(target, null,
                                                  BindingRestrictions.GetTypeRestriction(target.Expression, target.LimitType),
                                                  typeof(MissingMemberException), error));
            }
        }
示例#3
0
        /// <summary>
        /// Gets a <see cref="ComObject"/> that wraps the runtime-callable-wrapper, or creates one if none currently exists.
        /// </summary>
        /// <returns></returns>
        public static ComObject ObjectToComObject(object rcw)
        {
            Debug.Assert(ComBinder.IsComObject(rcw));

            object data = Marshal.GetComObjectData(rcw, s_comObjectInfoKey);

            if (data != null)
            {
                return((ComObject)data);
            }

            lock (s_comObjectInfoKey)
            {
                data = Marshal.GetComObjectData(rcw, s_comObjectInfoKey);
                if (data != null)
                {
                    return((ComObject)data);
                }

                ComObject comObjectInfo = CreateComObject(rcw);
                if (!Marshal.SetComObjectData(rcw, s_comObjectInfoKey, comObjectInfo))
                {
                    throw Error.SetComObjectDataFailed();
                }

                return(comObjectInfo);
            }
        }
        public override DynamicMetaObject FallbackInvokeMember(DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject?errorSuggestion)
        {
            // First try COM binding.
            if (ComBinder.TryBindInvokeMember(this, target, args, out var result))
            {
                return(result);
            }

            // Defer if any object has no value so that we evaluate their Expressions and nest a
            // CallSite for the InvokeMember.
            if (!target.HasValue || Array.Exists(args, a => !a.HasValue))
            {
                var deferArgs = new DynamicMetaObject[args.Length + 1];
                deferArgs[0] = target;
                args.CopyTo(deferArgs.AsSpan(1));
                return(Defer(deferArgs));
            }

            // Find our own binding. Could consider allowing invoking static members from an instance.
            var members = target.LimitType.GetMember(Name, BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Public);

            if (members.Length == 1 && (members[0] is PropertyInfo || members[0] is FieldInfo))
            {
                // NEED TO TEST, should check for delegate value too
                // var mem = members[0];
                throw new NotImplementedException();
                //return new DynamicMetaObject(
                //    Expression.Dynamic(
                //        new SymplInvokeBinder(new CallInfo(args.Length)),
                //        typeof(object),
                //        args.Select(a => a.Expression).AddFirst(
                //               Expression.MakeMemberAccess(this.Expression, mem)));

                // Don't test for eventinfos since we do nothing with them now.
            }
            else
            {
                // Get MethodInfos with param types that work for args. This works except for value
                // args that need to pass to reftype params. We could detect that to be smarter and
                // then explicitly StrongBox the args.
                var res = Array.FindAll(members, meth => meth is MethodInfo m && m.GetParameters().Length == args.Length && RuntimeHelpers.ParametersMatchArguments(m.GetParameters(), args));

                // False below means generate a type restriction on the MO. We are looking at the
                // members targetMO's Type.
                var restrictions = RuntimeHelpers.GetTargetArgsRestrictions(target, args, false);
                if (res.Length == 0)
                {
                    return(errorSuggestion ?? RuntimeHelpers.CreateThrow(target, args, restrictions,
                                                                         typeof(MissingMemberException), $"Can't bind member invoke -- {args}"));
                }

                // restrictions and conversion must be done consistently.
                var callArgs = RuntimeHelpers.ConvertArguments(args, ((MethodInfo)res[0]).GetParameters());
                return(new DynamicMetaObject(RuntimeHelpers.EnsureObjectResult(Expression.Call(Expression.Convert(target.Expression, target.LimitType), (MethodInfo)res[0], callArgs)), restrictions));
                // Could hve tried just letting expression.Call factory do the work, but if there is more
                // than one applicable method using just assignablefrom, expression.Call throws. It does
                // not pick a "most applicable" method or any method.
            }
        }
        public override DynamicMetaObject FallbackSetMember(DynamicMetaObject target, DynamicMetaObject value, DynamicMetaObject?errorSuggestion)
        {
            // First try COM binding.
            if (ComBinder.TryBindSetMember(this, target, value, out var result))
            {
                return(result);
            }

            // Defer if any object has no value so that we evaluate their Expressions and nest a
            // CallSite for the InvokeMember.
            if (!target.HasValue)
            {
                return(Defer(target));
            }

            // Find our own binding.
            var members = target.LimitType.GetMember(Name, BindingFlags.IgnoreCase | BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public);

            if (members.Length == 1)
            {
                var        mem = members[0];
                Expression val;
                switch (mem.MemberType)
                {
                // Should check for member domain type being Type and value being TypeModel, similar
                // to ConvertArguments, and building an expression like GetRuntimeTypeMoFromModel.
                case MemberTypes.Property:
                    val = Expression.Convert(value.Expression, ((PropertyInfo)mem).PropertyType);
                    break;

                case MemberTypes.Field:
                    val = Expression.Convert(value.Expression, ((FieldInfo)mem).FieldType);
                    break;

                default:
                    return(errorSuggestion ?? RuntimeHelpers.CreateThrow(target, null,
                                                                         BindingRestrictions.GetTypeRestriction(target.Expression, target.LimitType),
                                                                         typeof(InvalidOperationException),
                                                                         "Sympl only supports setting Properties and fields at this time."));
                }

                return(new DynamicMetaObject(
                           // Assign returns the stored value, so we're good for Sympl.
                           RuntimeHelpers.EnsureObjectResult(Expression.Assign(
                                                                 Expression.MakeMemberAccess(Expression.Convert(target.Expression, members[0].DeclaringType !),
                                                                                             members[0]), val)),
                           // Don't need restriction test for name since this rule is only used where binder
                           // is used, which is only used in sites with this binder.Name.
                           BindingRestrictions.GetTypeRestriction(target.Expression, target.LimitType)));
            }
            else
            {
                return(errorSuggestion ?? RuntimeHelpers.CreateThrow(target, null,
                                                                     BindingRestrictions.GetTypeRestriction(target.Expression, target.LimitType),
                                                                     typeof(MissingMemberException), "IDynObj member name conflict."));
            }
        }
示例#6
0
        public override DynamicMetaObject FallbackInvoke(
            DynamicMetaObject target,
            DynamicMetaObject[] args,
            DynamicMetaObject errorSuggestion)
        {
            DynamicMetaObject result;

            if (ComBinder.TryBindInvoke(this, target, args, out result))
            {
                return(result);
            }

            // Defer if any object has no value so that we evaulate their
            // Expressions and nest a CallSite for the InvokeMember.
            if (!target.HasValue || args.Any((a) => !a.HasValue))
            {
                var deferArgs = new DynamicMetaObject[args.Length + 1];

                for (int i = 0; i < args.Length; i++)
                {
                    deferArgs[i + 1] = args[i];
                }

                deferArgs[0] = target;

                return(Defer(deferArgs));
            }

            if (target.LimitType.IsSubclassOf(typeof(Delegate)))
            {
                var parms = target.LimitType.GetMethod("Invoke").GetParameters();
                if (parms.Length == args.Length)
                {
                    // Don't need to check if argument types match parameters.
                    // If they don't, users get an argument conversion error.
                    var callArgs = RuntimeHelpers.ConvertArguments(args, parms);

                    var expression = Expression.Invoke(
                        Expression.Convert(target.Expression, target.LimitType),
                        callArgs);

                    return(new DynamicMetaObject(
                               RuntimeHelpers.EnsureObjectResult(expression),
                               BindingRestrictions.GetTypeRestriction(target.Expression, target.LimitType)));
                }
            }

            return(errorSuggestion ??
                   RuntimeHelpers.CreateThrow(
                       target,
                       args,
                       BindingRestrictions.GetTypeRestriction(target.Expression, target.LimitType),
                       typeof(InvalidOperationException),
                       new string[] { $"Wrong number of arguments passed to function {target.LimitType} got {args}" }));
        }
        /// <summary>
        /// Performs the binding of the dynamic set member operation if the target dynamic object cannot bind.
        /// </summary>
        /// <param name="target">The target of the dynamic set member operation.</param>
        /// <param name="value">The value to set to the member.</param>
        /// <param name="errorSuggestion">The binding result to use if binding fails, or null.</param>
        /// <returns>The <see cref="DynamicMetaObject"/> representing the result of the binding.</returns>
        public override DynamicMetaObject FallbackSetMember(DynamicMetaObject target, DynamicMetaObject value, DynamicMetaObject errorSuggestion)
        {
#if !SILVERLIGHT
            DynamicMetaObject com;
            if (!BinderHelper.IsWindowsRuntimeObject(target) && ComBinder.TryBindSetMember(this, target, value, out com))
            {
                return(com);
            }
#endif
            return(BinderHelper.Bind(this, m_binder, new[] { target, value }, m_argumentInfo, errorSuggestion));
        }
示例#8
0
        /// <summary>
        /// Performs the binding of the dynamic convert operation if the target dynamic object cannot bind.
        /// </summary>
        /// <param name="target">The target of the dynamic convert operation.</param>
        /// <param name="errorSuggestion">The binding result to use if binding fails, or null.</param>
        /// <returns>The <see cref="DynamicMetaObject"/> representing the result of the binding.</returns>
        public override DynamicMetaObject FallbackConvert(DynamicMetaObject target, DynamicMetaObject errorSuggestion)
        {
#if ENABLECOMBINDER
            DynamicMetaObject com;
            if (!BinderHelper.IsWindowsRuntimeObject(target) && ComBinder.TryConvert(this, target, out com))
            {
                return(com);
            }
#endif
            return(BinderHelper.Bind(this, _binder, new[] { target }, null, errorSuggestion));
        }
        /// <summary>
        /// Performs the binding of the dynamic get member operation if the target dynamic object cannot bind.
        /// </summary>
        /// <param name="target">The target of the dynamic get member operation.</param>
        /// <param name="errorSuggestion">The binding result to use if binding fails, or null.</param>
        /// <returns>The <see cref="DynamicMetaObject"/> representing the result of the binding.</returns>
        public override DynamicMetaObject FallbackGetMember(DynamicMetaObject target, DynamicMetaObject errorSuggestion)
        {
#if ENABLECOMBINDER
            DynamicMetaObject com;
            if (!BinderHelper.IsWindowsRuntimeObject(target) && ComBinder.TryBindGetMember(this, target, out com, ResultIndexed))
            {
                return(com);
            }
#endif
            return(BinderHelper.Bind(this, _binder, new[] { target }, _argumentInfo, errorSuggestion));
        }
示例#10
0
        /// <summary>
        /// Performs the binding of the dynamic invoke member operation if the target dynamic object cannot bind.
        /// </summary>
        /// <param name="target">The target of the dynamic invoke member operation.</param>
        /// <param name="args">The arguments of the dynamic invoke member operation.</param>
        /// <param name="errorSuggestion">The binding result to use if binding fails, or null.</param>
        /// <returns>The <see cref="DynamicMetaObject"/> representing the result of the binding.</returns>
        public override DynamicMetaObject FallbackInvokeMember(DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject errorSuggestion)
        {
#if ENABLECOMBINDER
            DynamicMetaObject com;
            if (!BinderHelper.IsWindowsRuntimeObject(target) && ComBinder.TryBindInvokeMember(this, target, args, out com))
            {
                return(com);
            }
#endif
            return(BinderHelper.Bind(this, _binder, BinderHelper.Cons(target, args), _argumentInfo, errorSuggestion));
        }
        /// <summary>
        /// Performs the binding of the dynamic invoke operation if the target dynamic object cannot bind.
        /// </summary>
        /// <param name="target">The target of the dynamic invoke operation.</param>
        /// <param name="args">The arguments of the dynamic invoke operation.</param>
        /// <param name="errorSuggestion">The binding result to use if binding fails, or null.</param>
        /// <returns>The <see cref="DynamicMetaObject"/> representing the result of the binding.</returns>
        public override DynamicMetaObject FallbackInvoke(DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject errorSuggestion)
        {
#if !SILVERLIGHT
            DynamicMetaObject com;
            if (!BinderHelper.IsWindowsRuntimeObject(target) && ComBinder.TryBindInvoke(this, target, args, out com))
            {
                return(com);
            }
#endif
            return(BinderHelper.Bind(this, m_binder, BinderHelper.Cons(target, args), m_argumentInfo, errorSuggestion));
        }
示例#12
0
        /// <summary>
        /// Performs the binding of the dynamic set index operation if the target dynamic object cannot bind.
        /// </summary>
        /// <param name="target">The target of the dynamic set index operation.</param>
        /// <param name="indexes">The arguments of the dynamic set index operation.</param>
        /// <param name="value">The value to set to the collection.</param>
        /// <param name="errorSuggestion">The binding result to use if binding fails, or null.</param>
        /// <returns>The <see cref="DynamicMetaObject"/> representing the result of the binding.</returns>
        public override DynamicMetaObject FallbackSetIndex(DynamicMetaObject target, DynamicMetaObject[] indexes, DynamicMetaObject value, DynamicMetaObject errorSuggestion)
        {
#if ENABLECOMBINDER
            DynamicMetaObject com;
            if (!BinderHelper.IsWindowsRuntimeObject(target) && ComBinder.TryBindSetIndex(this, target, indexes, value, out com))
            {
                return(com);
            }
#endif
            return(BinderHelper.Bind(this, _binder, BinderHelper.Cons(target, indexes, value), _argumentInfo, errorSuggestion));
        }
示例#13
0
        /// <summary>
        /// Performs the binding of the dynamic get index operation if the target dynamic object cannot bind.
        /// </summary>
        /// <param name="target">The target of the dynamic get index operation.</param>
        /// <param name="indexes">The arguments of the dynamic get index operation.</param>
        /// <param name="errorSuggestion">The binding result to use if binding fails, or null.</param>
        /// <returns>The <see cref="DynamicMetaObject"/> representing the result of the binding.</returns>
        public override DynamicMetaObject FallbackGetIndex(DynamicMetaObject target, DynamicMetaObject[] indexes, DynamicMetaObject errorSuggestion)
        {
#if ENABLECOMBINDER
            DynamicMetaObject com;
            if (!BinderHelper.IsWindowsRuntimeObject(target) && ComBinder.TryBindGetIndex(this, target, indexes, out com))
            {
                return(com);
            }
#endif
            BinderHelper.ValidateBindArgument(target, nameof(target));
            BinderHelper.ValidateBindArgument(indexes, nameof(indexes));
            return(BinderHelper.Bind(this, _binder, BinderHelper.Cons(target, indexes), _argumentInfo, errorSuggestion));
        }
        /// <summary>
        /// Performs the binding of the dynamic set member operation if the target dynamic object cannot bind.
        /// </summary>
        /// <param name="target">The target of the dynamic set member operation.</param>
        /// <param name="value">The value to set to the member.</param>
        /// <param name="errorSuggestion">The binding result to use if binding fails, or null.</param>
        /// <returns>The <see cref="DynamicMetaObject"/> representing the result of the binding.</returns>
        public override DynamicMetaObject FallbackSetMember(DynamicMetaObject target, DynamicMetaObject value, DynamicMetaObject errorSuggestion)
        {
#if ENABLECOMBINDER
            DynamicMetaObject com;
            if (!BinderHelper.IsWindowsRuntimeObject(target) && ComBinder.TryBindSetMember(this, target, value, out com))
            {
                return(com);
            }
#endif
            BinderHelper.ValidateBindArgument(target, nameof(target));
            BinderHelper.ValidateBindArgument(value, nameof(value));
            return(BinderHelper.Bind(this, _binder, new[] { target, value }, _argumentInfo, errorSuggestion));
        }
示例#15
0
        /// <summary>
        /// Performs the binding of the dynamic convert operation if the target dynamic object cannot bind.
        /// </summary>
        /// <param name="target">The target of the dynamic convert operation.</param>
        /// <param name="errorSuggestion">The binding result to use if binding fails, or null.</param>
        /// <returns>The <see cref="DynamicMetaObject"/> representing the result of the binding.</returns>
        public override DynamicMetaObject FallbackConvert(DynamicMetaObject target, DynamicMetaObject errorSuggestion)
        {
#if ENABLECOMBINDER
            DynamicMetaObject com;
            if (!BinderHelper.IsWindowsRuntimeObject(target) && ComBinder.TryConvert(this, target, out com))
            {
                return(com);
            }
#else
            BinderHelper.ThrowIfUsingDynamicCom(target);
#endif

            BinderHelper.ValidateBindArgument(target, nameof(target));
            return(BinderHelper.Bind(this, _binder, new[] { target }, null, errorSuggestion));
        }
示例#16
0
        /// <summary>
        /// Performs the binding of the dynamic invoke operation if the target dynamic object cannot bind.
        /// </summary>
        /// <param name="target">The target of the dynamic invoke operation.</param>
        /// <param name="args">The arguments of the dynamic invoke operation.</param>
        /// <param name="errorSuggestion">The binding result to use if binding fails, or null.</param>
        /// <returns>The <see cref="DynamicMetaObject"/> representing the result of the binding.</returns>
        public override DynamicMetaObject FallbackInvoke(DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject errorSuggestion)
        {
#if ENABLECOMBINDER
            DynamicMetaObject com;
            if (!BinderHelper.IsWindowsRuntimeObject(target) && ComBinder.TryConvert(this, target, out com))
            {
                return(com);
            }
#else
            BinderHelper.ThrowIfUsingDynamicCom(target);
#endif

            BinderHelper.ValidateBindArgument(target, nameof(target));
            BinderHelper.ValidateBindArgument(args, nameof(args));
            return(BinderHelper.Bind(this, _binder, BinderHelper.Cons(target, args), _argumentInfo, errorSuggestion));
        }
示例#17
0
        public override DynamicMetaObject FallbackSetIndex(DynamicMetaObject target, DynamicMetaObject[] indexes, DynamicMetaObject value, DynamicMetaObject?errorSuggestion)
        {
            // First try COM binding.
            if (ComBinder.TryBindSetIndex(this, target, indexes, value, out var result))
            {
                return(result);
            }

            // Defer if any object has no value so that we evaulate their Expressions and nest a
            // CallSite for the InvokeMember.
            if (!target.HasValue || !value.HasValue || Array.Exists(indexes, a => !a.HasValue))
            {
                var deferArgs = new DynamicMetaObject[indexes.Length + 2];
                indexes.CopyTo(deferArgs.AsSpan(1));
                deferArgs[0]   = target;
                deferArgs[^ 1] = value;
        public override DynamicMetaObject FallbackGetMember(
            DynamicMetaObject targetMO, DynamicMetaObject errorSuggestion)
        {
#if !SILVERLIGHT
            // First try COM binding.
            DynamicMetaObject result;
            if (ComBinder.TryBindGetMember(this, targetMO, out result))
            {
                return(result);
            }
#endif
            // Defer if any object has no value so that we evaulate their
            // Expressions and nest a CallSite for the InvokeMember.
            if (!targetMO.HasValue)
            {
                return(Defer(targetMO));
            }
            // Find our own binding.
            var flags = BindingFlags.IgnoreCase | BindingFlags.Static |
                        BindingFlags.Instance | BindingFlags.Public;
            var members = targetMO.LimitType.GetMember(this.Name, flags);
            if (members.Length == 1)
            {
                return(new DynamicMetaObject(
                           RuntimeHelpers.EnsureObjectResult(
                               Expression.MakeMemberAccess(
                                   Expression.Convert(targetMO.Expression,
                                                      members[0].DeclaringType),
                                   members[0])),
                           // Don't need restriction test for name since this
                           // rule is only used where binder is used, which is
                           // only used in sites with this binder.Name.
                           BindingRestrictions.GetTypeRestriction(targetMO.Expression,
                                                                  targetMO.LimitType)));
            }
            else
            {
                return(errorSuggestion ??
                       RuntimeHelpers.CreateThrow(
                           targetMO, null,
                           BindingRestrictions.GetTypeRestriction(targetMO.Expression,
                                                                  targetMO.LimitType),
                           typeof(MissingMemberException),
                           "cannot bind member, " + this.Name +
                           ", on object " + targetMO.Value.ToString()));
            }
        }
示例#19
0
        public override DynamicMetaObject FallbackGetIndex(DynamicMetaObject target, DynamicMetaObject[] indexes, DynamicMetaObject errorSuggestion)
        {
            if (ComBinder.TryBindGetIndex(this, target, indexes, out DynamicMetaObject result))
            {
                return(result);
            }

            if (!target.HasValue || indexes.Any(x => !x.HasValue))
            {
                return(Defer(target, indexes));
            }

            var expression   = RuntimeHelpers.EnsureObjectResult(RuntimeHelpers.GetIndexingExpression(target, indexes));
            var restrictions = RuntimeHelpers.GetTargetArgsRestrictions(target, indexes, false);

            return(new DynamicMetaObject(expression, restrictions));
        }
示例#20
0
        public override DynamicMetaObject FallbackInvoke(DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject?errorSuggestion)
        {
            // First try COM binding.
            if (ComBinder.TryBindInvoke(this, target, args, out var result))
            {
                return(result);
            }

            // Defer if any object has no value so that we evaulate their Expressions and nest a
            // CallSite for the InvokeMember.
            if (!target.HasValue || Array.Exists(args, a => !a.HasValue))
            {
                var deferArgs = new DynamicMetaObject[args.Length + 1];
                deferArgs[0] = target;
                args.CopyTo(deferArgs.AsSpan(1));
                return(Defer(deferArgs));
            }

            // Find our own binding.
            if (!target.LimitType.IsSubclassOf(typeof(Delegate)))
            {
                return(errorSuggestion ?? RuntimeHelpers.CreateThrow(target, args,
                                                                     BindingRestrictions.GetTypeRestriction(target.Expression, target.LimitType),
                                                                     typeof(InvalidOperationException),
                                                                     $"Wrong number of arguments for function -- {target.LimitType} got {args}"));
            }

            var parameters = target.LimitType.GetMethod("Invoke") !.GetParameters();

            if (parameters.Length != args.Length)
            {
                return(errorSuggestion ?? RuntimeHelpers.CreateThrow(target, args,
                                                                     BindingRestrictions.GetTypeRestriction(target.Expression, target.LimitType),
                                                                     typeof(InvalidOperationException),
                                                                     $"Wrong number of arguments for function -- {target.LimitType} got {args}"));
            }


            // Don't need to check if argument types match parameters. If they don't, users
            // get an argument conversion error.
            var callArgs   = RuntimeHelpers.ConvertArguments(args, parameters);
            var expression = Expression.Invoke(Expression.Convert(target.Expression, target.LimitType), callArgs);

            return(new DynamicMetaObject(RuntimeHelpers.EnsureObjectResult(expression), BindingRestrictions.GetTypeRestriction(target.Expression, target.LimitType)));
        }
示例#21
0
        public override DynamicMetaObject FallbackInvoke(DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject errorSuggestion)
        {
            if (ComBinder.TryBindInvoke(this, target, args, out DynamicMetaObject res))
            {
                return(res);
            }

            return(errorSuggestion ?? new DynamicMetaObject(
                       Expression.Throw(
                           Expression.New(
                               typeof(NotSupportedException).GetConstructor(new[] { typeof(string) }),
                               Expression.Constant(ParserStrings.CannotCall)
                               ),
                           typeof(object)
                           ),
                       target.Restrictions.Merge(BindingRestrictions.Combine(args))
                       ));
        }
示例#22
0
        public override DynamicMetaObject FallbackSetIndex(DynamicMetaObject target, DynamicMetaObject[] indexes, DynamicMetaObject value, DynamicMetaObject errorSuggestion)
        {
            if (ComBinder.TryBindSetIndex(this, target, indexes, value, out DynamicMetaObject result))
            {
                return(result);
            }

            if (!target.HasValue || !value.HasValue || indexes.Any(x => !x.HasValue))
            {
                return(Defer(target, indexes));
            }

            var arrayAccess = RuntimeHelpers.GetIndexingExpression(target, indexes);
            var setIndex    = Expression.Assign(arrayAccess, Expression.Convert(value.Expression, value.LimitType));

            var restrictions = RuntimeHelpers.GetTargetArgsRestrictions(target, indexes, false);

            return(new DynamicMetaObject(RuntimeHelpers.EnsureObjectResult(setIndex), restrictions));
        }
示例#23
0
        public override DynamicMetaObject FallbackGetIndex(
            DynamicMetaObject target, DynamicMetaObject[] indexes,
            DynamicMetaObject errorSuggestion)
        {
#if !SILVERLIGHT
            // First try COM binding.
            DynamicMetaObject result;
            if (ComBinder.TryBindGetIndex(this, target, indexes, out result))
            {
                return(result);
            }
#endif
            // Defer if any object has no value so that we evaulate their
            // Expressions and nest a CallSite for the InvokeMember.
            if (!target.HasValue || indexes.Any((a) => !a.HasValue))
            {
                var deferArgs = new DynamicMetaObject[indexes.Length + 1];
                for (int i = 0; i < indexes.Length; i++)
                {
                    deferArgs[i + 1] = indexes[i];
                }
                deferArgs[0] = target;
                return(Defer(deferArgs));
            }

            var restrictions = RuntimeHelpers.GetTargetArgsRestrictions(
                target, indexes, false);

            if (target.HasValue && target.Value == null)
            {
                return(errorSuggestion ?? RuntimeHelpers.CreateThrow(target,
                                                                     indexes,
                                                                     restrictions,
                                                                     typeof(NullReferenceException),
                                                                     "Object reference not set to an instance of an object."));
            }
            var indexingExpr = RuntimeHelpers.EnsureObjectResult(
                RuntimeHelpers.GetIndexingExpression(target,
                                                     indexes));
            return(new DynamicMetaObject(indexingExpr, restrictions));
        }
示例#24
0
        public override DynamicMetaObject FallbackGetIndex(DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject?errorSuggestion)
        {
            // First try COM binding.
            if (ComBinder.TryBindGetIndex(this, target, args, out var result))
            {
                return(result);
            }

            // Defer if any object has no value so that we evaulate their Expressions and nest a
            // CallSite for the InvokeMember.
            if (!target.HasValue || Array.Exists(args, a => !a.HasValue))
            {
                var deferArgs = new DynamicMetaObject[args.Length + 1];
                deferArgs[0] = target;
                args.CopyTo(deferArgs.AsSpan(1));

                return(Defer(deferArgs));
            }

            // Give good error for Cons.
            if (target.LimitType == typeof(Cons))
            {
                if (args.Length != 1)
                {
                    return(errorSuggestion ?? RuntimeHelpers.CreateThrow(target, args, BindingRestrictions.Empty,
                                                                         typeof(InvalidOperationException),
                                                                         $"Indexing list takes single index. Got {args.Length}"));
                }
            }

            // Find our own binding.
            // Conversions created in GetIndexExpression must be consistent with restrictions made in GetTargetArgsRestrictions.
            var indexingExpr = RuntimeHelpers.EnsureObjectResult(RuntimeHelpers.GetIndexingExpression(target, args));
            var restrictions = RuntimeHelpers.GetTargetArgsRestrictions(target, args, false);

            return(new DynamicMetaObject(indexingExpr, restrictions));
        }
示例#25
0
 internal ComObject(object rcw)
 {
     Debug.Assert(ComBinder.IsComObject(rcw));
     RuntimeCallableWrapper = rcw;
 }
        public override DynamicMetaObject FallbackInvokeMember(
            DynamicMetaObject target,
            DynamicMetaObject[] args,
            DynamicMetaObject errorSuggestion)
        {
            DynamicMetaObject result;

            if (ComBinder.TryBindInvokeMember(this, target, args, out result))
            {
                return(result);
            }

            // Defer if any object has no value so that we evaulate their
            // Expressions and nest a CallSite for the InvokeMember.
            if (!target.HasValue || args.Any((a) => !a.HasValue))
            {
                var deferArgs = new DynamicMetaObject[args.Length + 1];

                for (int i = 0; i < args.Length; i++)
                {
                    deferArgs[i + 1] = args[i];
                }

                deferArgs[0] = target;

                return(Defer(deferArgs));
            }

            var flags    = BindingFlags.Instance | BindingFlags.Public | BindingFlags.Static;
            var members  = Array.Empty <MemberInfo>();
            var isStatic = false;

            if (target.RuntimeType == typeof(UnresolvedType))
            {
                if (runtime.TypeProvider.TryGetType(target.Value as UnresolvedType, out Type type))
                {
                    members  = type.GetMember(Name, flags);
                    isStatic = true;
                }
            }
            else
            {
                members = target.LimitType.GetMember(Name, flags);
            }

            if ((members.Length == 1) && (members[0] is PropertyInfo || members[0] is FieldInfo))
            {
                // NEED TO TEST, should check for delegate value too
                var mem = members[0];
                throw new NotImplementedException();
                //return new DynamicMetaObject(
                //    Expression.Dynamic(
                //        new RilaInvokeBinder(new CallInfo(args.Length)),
                //        typeof(object),
                //        args.Select(a => a.Expression).AddFirst(
                //               Expression.MakeMemberAccess(this.Expression, mem)));

                // Don't test for eventinfos since we do nothing with them now.
            }
            else
            {
                // Get MethodInfos with right arg counts.
                var methodInfos = members.Where(x =>
                                                x.MemberType == MemberTypes.Method && ((MethodInfo)x).GetParameters().Length == args.Length);

                // Get MethodInfos with param types that work for args.  This works
                // except for value args that need to pass to reftype params.
                // We could detect that to be smarter and then explicitly StrongBox
                // the args.
                List <MethodInfo> res = new List <MethodInfo>();

                foreach (MethodInfo info in methodInfos)
                {
                    if (RuntimeHelpers.ParametersMatchArguments(info.GetParameters(), args))
                    {
                        res.Add(info);
                    }
                }
                // False below means generate a type restriction on the MO.
                // We are looking at the members targetMO's Type.
                var restrictions = RuntimeHelpers.GetTargetArgsRestrictions(target, args, false);

                if (res.Count == 0)
                {
                    var argTypes    = args.Select(x => x.RuntimeType.Name).ToArray();
                    var typesString = string.Join(", ", argTypes);

                    return(errorSuggestion ??
                           RuntimeHelpers.CreateThrow(target, args, restrictions, typeof(MissingMemberException),
                                                      new string[] { $"Missing member {typesString} for method \"{Name}\"." }));
                }

                // restrictions and conversion must be done consistently.
                var callArgs = RuntimeHelpers.ConvertArguments(args, res[0].GetParameters());

                if (isStatic)
                {
                    return(new DynamicMetaObject(
                               RuntimeHelpers.EnsureObjectResult(Expression.Call(null, res[0], callArgs)),
                               restrictions));
                }

                return(new DynamicMetaObject(
                           RuntimeHelpers.EnsureObjectResult(
                               Expression.Call(
                                   Expression.Convert(target.Expression, target.LimitType),
                                   res[0], callArgs)),
                           restrictions));
            }
        }
示例#27
0
        public override DynamicMetaObject FallbackGetMember(DynamicMetaObject target, DynamicMetaObject errorSuggestion)
        {
            DynamicMetaObject result;

            if (ComBinder.TryBindGetMember(this, target, out result, true))
            {
                return(result);
            }

            if (!target.HasValue)
            {
                return(Defer(target));
            }

            var flags    = BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public;
            var members  = Array.Empty <MemberInfo>();
            var isStatic = false;

            if (target.RuntimeType == typeof(UnresolvedType))
            {
                var unresolved = target.Value as UnresolvedType;

                if (runtime.TypeProvider.IsAlias(unresolved.Name))
                {
                    //Simply pass the name of the member we are trying to access as that is the actual member name
                    return(new DynamicMetaObject(
                               Expression.Constant(new UnresolvedType(Name)), BindingRestrictions.Empty));
                }

                if (runtime.TypeProvider.TryGetType(unresolved, out Type type))
                {
                    members  = type.GetMember(Name, flags);
                    isStatic = true;
                }
            }
            else
            {
                members = target.LimitType.GetMember(Name, flags);
            }

            if (members.Length == 1)
            {
                if (isStatic)
                {
                    return(new DynamicMetaObject(
                               RuntimeHelpers.EnsureObjectResult(
                                   Expression.MakeMemberAccess(null, members[0])),
                               BindingRestrictions.GetTypeRestriction(target.Expression, target.LimitType)));
                }


                return(new DynamicMetaObject(
                           RuntimeHelpers.EnsureObjectResult(
                               Expression.MakeMemberAccess(
                                   Expression.Convert(target.Expression, members[0].DeclaringType), members[0])),
                           // Don't need restriction test for name since this
                           // rule is only used where binder is used, which is
                           // only used in sites with this binder.Name.
                           BindingRestrictions.GetTypeRestriction(target.Expression, target.LimitType)));
            }
            else
            {
                var error = new string[] { $"Object \"{target.Value.ToString()}\" doesn't contain a member named \"{Name}\"" };

                return(errorSuggestion ??
                       RuntimeHelpers.CreateThrow(
                           target, null,
                           BindingRestrictions.GetTypeRestriction(target.Expression, target.LimitType),
                           typeof(MissingMemberException),
                           error));
            }
        }
示例#28
0
        public override DynamicMetaObject FallbackInvokeMember(
            DynamicMetaObject targetMO, DynamicMetaObject[] args,
            DynamicMetaObject errorSuggestion)
        {
#if !NETSTANDARD
            // First try COM binding.
            DynamicMetaObject result;
            if (ComBinder.TryBindInvokeMember(this, targetMO, args, out result))
            {
                return(result);
            }
#endif
            // Defer if any object has no value so that we evaulate their
            // Expressions and nest a CallSite for the InvokeMember.
            if (!targetMO.HasValue || args.Any((a) => !a.HasValue))
            {
                var deferArgs = new DynamicMetaObject[args.Length + 1];
                for (int i = 0; i < args.Length; i++)
                {
                    deferArgs[i + 1] = args[i];
                }
                deferArgs[0] = targetMO;
                return(Defer(deferArgs));
            }
            // Find our own binding.
            // Could consider allowing invoking static members from an instance.
            var flags = BindingFlags.IgnoreCase | BindingFlags.Instance |
                        BindingFlags.Public;
            var members = targetMO.LimitType.GetMember(this.Name, flags);

            var restrictions = RuntimeHelpers.GetTargetArgsRestrictions(
                targetMO, args, false);

            // Assigned a Null
            if (targetMO.HasValue && targetMO.Value == null)
            {
                return(RuntimeHelpers.CreateThrow(targetMO,
                                                  args,
                                                  restrictions,
                                                  typeof(NullReferenceException),
                                                  "Object reference not set to an instance of an object."));
            }

            if ((members.Length == 1) && (members[0] is PropertyInfo ||
                                          members[0] is FieldInfo))
            {
                // NEED TO TEST, should check for delegate value too
                var mem    = members[0];
                var target = new DynamicMetaObject(
                    RuntimeHelpers.EnsureObjectResult(
                        Expression.MakeMemberAccess(
                            Expression.Convert(targetMO.Expression,
                                               members[0].DeclaringType),
                            members[0])),
                    // Don't need restriction test for name since this
                    // rule is only used where binder is used, which is
                    // only used in sites with this binder.Name.
                    BindingRestrictions.GetTypeRestriction(targetMO.Expression,
                                                           targetMO.LimitType));

                //If no arguments, to allow scenario like Request.QueryString()
                if (args == null || args.Length == 0)
                {
                    return(target);
                }

                return(new DynamicMetaObject(
                           RuntimeHelpers.GetIndexingExpression(target, args),
                           restrictions
                           ));
                // Don't test for eventinfos since we do nothing with them now.
            }
            else
            {
                bool isExtension = false;

                // Get MethodInfos with right arg counts.
                var mi_mems = members.
                              Select(m => m as MethodInfo).
                              Where(m => m is MethodInfo &&
                                    ((MethodInfo)m).GetParameters().Length ==
                                    args.Length);
                // Get MethodInfos with param types that work for args.  This works
                // except for value args that need to pass to reftype params.
                // We could detect that to be smarter and then explicitly StrongBox
                // the args.
                List <MethodInfo> res = new List <MethodInfo>();
                foreach (var mem in mi_mems)
                {
                    if (RuntimeHelpers.ParametersMatchArguments(
                            mem.GetParameters(), args))
                    {
                        res.Add(mem);
                    }
                }

                List <DynamicMetaObject> argList = new List <DynamicMetaObject>(args);

                //Try extension methods if no methods found
                if (res.Count == 0)
                {
                    isExtension = true;
                    argList.Insert(0, targetMO);

                    res = RuntimeHelpers.GetExtensionMethods(this.Name, targetMO, argList.ToArray());
                }

                // False below means generate a type restriction on the MO.
                // We are looking at the members targetMO's Type.
                if (res.Count == 0)
                {
                    return(errorSuggestion ??
                           RuntimeHelpers.CreateThrow(
                               targetMO, args, restrictions,
                               typeof(MissingMemberException),
                               string.Format("Can't bind member invoke {0}.{1}({2})", targetMO.RuntimeType.Name, this.Name, args.ToString())));
                }

                //If more than one results found, attempt overload resolution
                MethodInfo mi = null;
                if (res.Count > 1)
                {
                    mi = RuntimeHelpers.ResolveOverload(res, argList.ToArray());
                }
                else
                {
                    mi = res[0];
                }

                // restrictions and conversion must be done consistently.
                var callArgs = RuntimeHelpers.ConvertArguments(
                    argList.ToArray(), mi.GetParameters());

                if (isExtension)
                {
                    return(new DynamicMetaObject(
                               RuntimeHelpers.EnsureObjectResult(
                                   Expression.Call(
                                       null,
                                       mi, callArgs)),
                               restrictions));
                }
                else
                {
                    return(new DynamicMetaObject(
                               RuntimeHelpers.EnsureObjectResult(
                                   Expression.Call(
                                       Expression.Convert(targetMO.Expression,
                                                          targetMO.LimitType),
                                       mi, callArgs)),
                               restrictions));
                }
                // Could hve tried just letting Expr.Call factory do the work,
                // but if there is more than one applicable method using just
                // assignablefrom, Expr.Call throws.  It does not pick a "most
                // applicable" method or any method.
            }
        }