1 /* ****************************************************************************
3 * Copyright (c) Microsoft Corporation.
5 * This source code is subject to terms and conditions of the Microsoft Public License. A
6 * copy of the license can be found in the License.html file at the root of this distribution. If
7 * you cannot locate the Microsoft Public License, please send an email to
8 * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
9 * by the terms of the Microsoft Public License.
11 * You must not remove this notice, or any other, from this software.
14 * ***************************************************************************/
15 using System; using Microsoft;
20 using System.Collections.ObjectModel;
21 using System.Diagnostics;
23 using System.Linq.Expressions;
25 using Microsoft.Linq.Expressions;
27 using System.Runtime.CompilerServices;
29 using Microsoft.Runtime.CompilerServices;
34 namespace System.Dynamic {
36 namespace Microsoft.Scripting {
39 /// Invokes the object. If it falls back, just produce an error.
41 internal sealed class ComInvokeAction : InvokeBinder {
42 internal ComInvokeAction(CallInfo callInfo)
46 public override int GetHashCode() {
47 return base.GetHashCode();
50 public override bool Equals(object obj) {
51 return base.Equals(obj as ComInvokeAction);
54 public override DynamicMetaObject FallbackInvoke(DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject errorSuggestion) {
55 return errorSuggestion ?? new DynamicMetaObject(
58 typeof(NotSupportedException).GetConstructor(new[] { typeof(string) }),
59 Expression.Constant(Strings.CannotCall)
62 target.Restrictions.Merge(BindingRestrictions.Combine(args))
68 /// Splats the arguments to another nested dynamic site, which does the
69 /// real invocation of the IDynamicMetaObjectProvider.
71 internal sealed class SplatInvokeBinder : CallSiteBinder {
72 internal readonly static SplatInvokeBinder Instance = new SplatInvokeBinder();
74 // Just splat the args and dispatch through a nested site
75 public override Expression Bind(object[] args, ReadOnlyCollection<ParameterExpression> parameters, LabelTarget returnLabel) {
76 Debug.Assert(args.Length == 2);
78 int count = ((object[])args[1]).Length;
79 ParameterExpression array = parameters[1];
81 var nestedArgs = new ReadOnlyCollectionBuilder<Expression>(count + 1);
82 var delegateArgs = new Type[count + 3]; // args + target + returnType + CallSite
83 nestedArgs.Add(parameters[0]);
84 delegateArgs[0] = typeof(CallSite);
85 delegateArgs[1] = typeof(object);
86 for (int i = 0; i < count; i++) {
87 nestedArgs.Add(Expression.ArrayAccess(array, Expression.Constant(i)));
88 delegateArgs[i + 2] = typeof(object).MakeByRefType();
90 delegateArgs[delegateArgs.Length - 1] = typeof(object);
92 return Expression.IfThen(
93 Expression.Equal(Expression.ArrayLength(array), Expression.Constant(count)),
96 Expression.MakeDynamic(
97 Expression.GetDelegateType(delegateArgs),
98 new ComInvokeAction(new CallInfo(count)),