コード例 #1
0
 /// <summary>
 /// When overridden in the derived class, performs the binding of the dynamic create operation if the target dynamic object cannot bind.
 /// </summary>
 /// <param name="target">The target of the dynamic create operation.</param>
 /// <param name="args">The arguments of the dynamic create 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 abstract DynamicMetaObject FallbackCreateInstance(DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject?errorSuggestion);
コード例 #2
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)));
        }
コード例 #3
0
 /// <summary>
 /// When overridden in the derived class, performs the binding of the dynamic delete index operation if the target dynamic object cannot bind.
 /// </summary>
 /// <param name="target">The target of the dynamic delete index operation.</param>
 /// <param name="indexes">The arguments of the dynamic delete 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 abstract DynamicMetaObject FallbackDeleteIndex(DynamicMetaObject target, DynamicMetaObject[] indexes, DynamicMetaObject?errorSuggestion);
コード例 #4
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 abstract DynamicMetaObject FallbackInvoke(DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject?errorSuggestion);
コード例 #5
0
ファイル: ConvertBinder.cs プロジェクト: csharpHub/Theraot
 /// <summary>
 ///     When overridden in the derived class, 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 abstract DynamicMetaObject FallbackConvert(DynamicMetaObject target, DynamicMetaObject?errorSuggestion);
コード例 #6
0
        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."));
            }
        }
コード例 #7
0
        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}"));
        }
コード例 #8
0
 /// <summary>
 /// When overridden in the derived class, 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 abstract DynamicMetaObject FallbackGetMember(DynamicMetaObject target, DynamicMetaObject?errorSuggestion);
コード例 #9
0
        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.
            }
        }
コード例 #10
0
        public override DynamicMetaObject FallbackInvoke(DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject?errorSuggestion)
        {
            var argExpressions = new Expression[args.Length + 1];

            for (var i = 0; i < args.Length; i++)
            {
                argExpressions[i + 1] = args[i].Expression;
            }

            argExpressions[0] = target.Expression;
            // Just "defer" since we have code in SymplInvokeBinder that knows what to do, and
            // typically this fallback is from a language like Python that passes a DynamicMetaObject
            // with HasValue == false.
            return(new DynamicMetaObject(Expression.Dynamic(
                                             // This call site doesn't share any L2 caching since we don't call
                                             // GetInvokeBinder from Sympl. We aren't plumbed to get the runtime instance here.
                                             new SymplInvokeBinder(new CallInfo(args.Length)), typeof(Object), // ret type
                                             argExpressions),
                                                                                                               // No new restrictions since SymplInvokeBinder will handle it.
                                         target.Restrictions.Merge(BindingRestrictions.Combine(args))));
        }
コード例 #11
0
        public override DynamicMetaObject FallbackCreateInstance(DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject?errorSuggestion)
        {
            // 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));
            }

            // Make sure target actually contains a Type.
            if (!typeof(Type).IsAssignableFrom(target.LimitType))
            {
                return(errorSuggestion ?? RuntimeHelpers.CreateThrow(target, args, BindingRestrictions.Empty,
                                                                     typeof(InvalidOperationException),
                                                                     $"Type object must be used when creating instance -- {args}"));
            }

            var type = target.Value as Type;

            Debug.Assert(type is not null);
            var constructors = type.GetConstructors();
            // Get constructors with right arg counts.

            var res = Array.FindAll(constructors, c => c.GetParameters().Length == args.Length && RuntimeHelpers.ParametersMatchArguments(c.GetParameters(), args));

            // We generate an instance restriction on the target since it is a Type and the
            // constructor is associate with the actual Type instance.
            var restrictions = RuntimeHelpers.GetTargetArgsRestrictions(target, args, true);

            if (res.Length == 0)
            {
                return(errorSuggestion ?? RuntimeHelpers.CreateThrow(target, args, restrictions,
                                                                     typeof(MissingMemberException),
                                                                     $"Can't bind create instance -- {args}"));
            }

            var ctorArgs = RuntimeHelpers.ConvertArguments(args, res[0].GetParameters());

            return(new DynamicMetaObject(
                       // Creating an object, so don't need EnsureObjectResult.
                       Expression.New(res[0], ctorArgs), restrictions));
        }
コード例 #12
0
 FallbackSetMember(DynamicMetaObject target, DynamicMetaObject value, DynamicMetaObject?errorSuggestion) =>
 errorSuggestion ?? RuntimeHelpers.CreateThrow(target, null, BindingRestrictions.Empty,
                                               typeof(MissingMemberException),
                                               "If IDynObj doesn't support setting members, DOHelpers can't do it for the IDO.");
コード例 #13
0
 FallbackGetMember(DynamicMetaObject target, DynamicMetaObject?errorSuggestion) =>
 errorSuggestion ?? new DynamicMetaObject(Expression.Constant(Sentinel),
                                          target.Restrictions.Merge(BindingRestrictions.GetTypeRestriction(target.Expression, target.LimitType)));
コード例 #14
0
        public override DynamicMetaObject FallbackGetMember(DynamicMetaObject target, DynamicMetaObject?errorSuggestion)
        {
            var instance = Expression.Call(
                DynamicGetMemberMethod,
                target.Expression,
                Expression.Constant(Name),
                Expression.Constant(IgnoreCase));

            return(DynamicMetaObject.Create(target.Value !, instance));
        }
コード例 #15
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;
コード例 #16
0
 public override DynamicMetaObject FallbackGetMember(DynamicMetaObject target, DynamicMetaObject?errorSuggestion)
 {
     throw new NotSupportedException();
 }
コード例 #17
0
        public override DynamicMetaObject FallbackBinaryOperation(DynamicMetaObject target, DynamicMetaObject arg, DynamicMetaObject?errorSuggestion)
        {
            // Defer if any object has no value so that we evaluate their Expressions and nest a
            // CallSite for the InvokeMember.
            if (!target.HasValue || !arg.HasValue)
            {
                return(Defer(target, arg));
            }

            var restrictions = target.Restrictions.Merge(arg.Restrictions)
                               .Merge(BindingRestrictions.GetTypeRestriction(target.Expression, target.LimitType))
                               .Merge(BindingRestrictions.GetTypeRestriction(arg.Expression, arg.LimitType));

            return(new DynamicMetaObject(
                       RuntimeHelpers.EnsureObjectResult(Expression.MakeBinary(Operation,
                                                                               Expression.Convert(target.Expression, target.LimitType),
                                                                               Expression.Convert(arg.Expression, arg.LimitType))), restrictions));
        }
コード例 #18
0
 /// <summary>
 /// When overridden in the derived class, 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 abstract DynamicMetaObject FallbackSetIndex(DynamicMetaObject target, DynamicMetaObject[] indexes, DynamicMetaObject value, DynamicMetaObject?errorSuggestion);
コード例 #19
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));
        }
コード例 #20
0
 /// <summary>
 /// When overridden in the derived class, performs the binding of the binary dynamic operation if the target dynamic object cannot bind.
 /// </summary>
 /// <param name="target">The target of the dynamic binary operation.</param>
 /// <param name="arg">The right hand side operand of the dynamic binary operation.</param>
 /// <param name="errorSuggestion">The binding result in case the binding fails, or null.</param>
 /// <returns>The <see cref="DynamicMetaObject"/> representing the result of the binding.</returns>
 public abstract DynamicMetaObject FallbackBinaryOperation(DynamicMetaObject target, DynamicMetaObject arg, DynamicMetaObject?errorSuggestion);
コード例 #21
0
 public override DynamicMetaObject FallbackUnaryOperation(DynamicMetaObject target, DynamicMetaObject?errorSuggestion) =>
 // Defer if any object has no value so that we evaluate their Expressions and nest a
 // CallSite for the InvokeMember.
 target.HasValue
         ? new DynamicMetaObject(
     RuntimeHelpers.EnsureObjectResult(Expression.MakeUnary(Operation,
                                                            Expression.Convert(target.Expression, target.LimitType), target.LimitType)),
     target.Restrictions.Merge(
         BindingRestrictions.GetTypeRestriction(target.Expression, target.LimitType)))
         : Defer(target);