1 /* ****************************************************************************
3 * Copyright (c) Microsoft Corporation.
5 * This source code is subject to terms and conditions of the Apache License, Version 2.0. 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 Apache License, Version 2.0, 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 Apache License, Version 2.0.
11 * You must not remove this notice, or any other, from this software.
14 * ***************************************************************************/
17 using System.Collections.Generic;
18 using System.Collections.ObjectModel;
19 using System.Diagnostics;
20 using System.Dynamic.Utils;
21 using System.Reflection;
22 using System.Runtime.CompilerServices;
25 namespace Microsoft.Scripting.Ast {
27 namespace System.Linq.Expressions {
32 /// Represents a dynamic operation.
34 [DebuggerTypeProxy(typeof(Expression.DynamicExpressionProxy))]
35 public class DynamicExpression : Expression, IArgumentProvider {
36 private readonly CallSiteBinder _binder;
37 private readonly Type _delegateType;
39 internal DynamicExpression(Type delegateType, CallSiteBinder binder) {
40 Debug.Assert(delegateType.GetMethod("Invoke").GetReturnType() == typeof(object) || GetType() != typeof(DynamicExpression));
41 _delegateType = delegateType;
45 internal static DynamicExpression Make(Type returnType, Type delegateType, CallSiteBinder binder, ReadOnlyCollection<Expression> arguments) {
46 if (returnType == typeof(object)) {
47 return new DynamicExpressionN(delegateType, binder, arguments);
49 return new TypedDynamicExpressionN(returnType, delegateType, binder, arguments);
53 internal static DynamicExpression Make(Type returnType, Type delegateType, CallSiteBinder binder, Expression arg0) {
54 if (returnType == typeof(object)) {
55 return new DynamicExpression1(delegateType, binder, arg0);
57 return new TypedDynamicExpression1(returnType, delegateType, binder, arg0);
61 internal static DynamicExpression Make(Type returnType, Type delegateType, CallSiteBinder binder, Expression arg0, Expression arg1) {
62 if (returnType == typeof(object)) {
63 return new DynamicExpression2(delegateType, binder, arg0, arg1);
65 return new TypedDynamicExpression2(returnType, delegateType, binder, arg0, arg1);
69 internal static DynamicExpression Make(Type returnType, Type delegateType, CallSiteBinder binder, Expression arg0, Expression arg1, Expression arg2) {
70 if (returnType == typeof(object)) {
71 return new DynamicExpression3(delegateType, binder, arg0, arg1, arg2);
73 return new TypedDynamicExpression3(returnType, delegateType, binder, arg0, arg1, arg2);
77 internal static DynamicExpression Make(Type returnType, Type delegateType, CallSiteBinder binder, Expression arg0, Expression arg1, Expression arg2, Expression arg3) {
78 if (returnType == typeof(object)) {
79 return new DynamicExpression4(delegateType, binder, arg0, arg1, arg2, arg3);
81 return new TypedDynamicExpression4(returnType, delegateType, binder, arg0, arg1, arg2, arg3);
86 /// Gets the static type of the expression that this <see cref="Expression" /> represents.
88 /// <returns>The <see cref="Type"/> that represents the static type of the expression.</returns>
89 public override Type Type {
90 get { return typeof(object); }
94 /// Returns the node type of this Expression. Extension nodes should return
95 /// ExpressionType.Extension when overriding this method.
97 /// <returns>The <see cref="ExpressionType"/> of the expression.</returns>
98 public sealed override ExpressionType NodeType {
99 get { return ExpressionType.Dynamic; }
103 /// Gets the <see cref="CallSiteBinder" />, which determines the runtime behavior of the
106 public CallSiteBinder Binder {
107 get { return _binder; }
111 /// Gets the type of the delegate used by the <see cref="CallSite" />.
113 public Type DelegateType {
114 get { return _delegateType; }
118 /// Gets the arguments to the dynamic operation.
120 public ReadOnlyCollection<Expression> Arguments {
121 get { return GetOrMakeArguments(); }
124 internal virtual ReadOnlyCollection<Expression> GetOrMakeArguments() {
125 throw ContractUtils.Unreachable;
129 /// Dispatches to the specific visit method for this node type.
131 protected internal override Expression Accept(ExpressionVisitor visitor) {
132 return visitor.VisitDynamic(this);
136 /// Makes a copy of this node replacing the args with the provided values. The
137 /// number of the args needs to match the number of the current block.
139 /// This helper is provided to allow re-writing of nodes to not depend on the specific optimized
140 /// subclass of DynamicExpression which is being used.
142 internal virtual DynamicExpression Rewrite(Expression[] args) {
143 throw ContractUtils.Unreachable;
147 /// Creates a new expression that is like this one, but using the
148 /// supplied children. If all of the children are the same, it will
149 /// return this expression.
151 /// <param name="arguments">The <see cref="Arguments" /> property of the result.</param>
152 /// <returns>This expression if no children changed, or an expression with the updated children.</returns>
153 public DynamicExpression Update(IEnumerable<Expression> arguments) {
154 if (arguments == Arguments) {
158 return Expression.MakeDynamic(DelegateType, Binder, arguments);
161 #region IArgumentProvider Members
163 Expression IArgumentProvider.GetArgument(int index) {
164 throw ContractUtils.Unreachable;
167 int IArgumentProvider.ArgumentCount {
168 get { throw ContractUtils.Unreachable; }
174 #region Specialized Subclasses
176 internal class DynamicExpressionN : DynamicExpression, IArgumentProvider {
177 private IList<Expression> _arguments; // storage for the original IList or readonly collection. See IArgumentProvider for more info.
179 internal DynamicExpressionN(Type delegateType, CallSiteBinder binder, IList<Expression> arguments)
180 : base(delegateType, binder) {
181 _arguments = arguments;
184 Expression IArgumentProvider.GetArgument(int index) {
185 return _arguments[index];
188 int IArgumentProvider.ArgumentCount {
190 return _arguments.Count;
194 internal override ReadOnlyCollection<Expression> GetOrMakeArguments() {
195 return ReturnReadOnly(ref _arguments);
198 internal override DynamicExpression Rewrite(Expression[] args) {
199 Debug.Assert(args.Length == ((IArgumentProvider)this).ArgumentCount);
201 return Expression.MakeDynamic(DelegateType, Binder, args);
205 internal class TypedDynamicExpressionN : DynamicExpressionN {
206 private readonly Type _returnType;
208 internal TypedDynamicExpressionN(Type returnType, Type delegateType, CallSiteBinder binder, IList<Expression> arguments)
209 : base(delegateType, binder, arguments) {
210 Debug.Assert(delegateType.GetMethod("Invoke").GetReturnType() == returnType);
211 _returnType = returnType;
214 public sealed override Type Type {
215 get { return _returnType; }
219 internal class DynamicExpression1 : DynamicExpression, IArgumentProvider {
220 private object _arg0; // storage for the 1st argument or a readonly collection. See IArgumentProvider for more info.
222 internal DynamicExpression1(Type delegateType, CallSiteBinder binder, Expression arg0)
223 : base(delegateType, binder) {
227 Expression IArgumentProvider.GetArgument(int index) {
229 case 0: return ReturnObject<Expression>(_arg0);
230 default: throw new InvalidOperationException();
234 int IArgumentProvider.ArgumentCount {
240 internal override ReadOnlyCollection<Expression> GetOrMakeArguments() {
241 return ReturnReadOnly(this, ref _arg0);
244 internal override DynamicExpression Rewrite(Expression[] args) {
245 Debug.Assert(args.Length == 1);
247 return Expression.MakeDynamic(DelegateType, Binder, args[0]);
251 internal sealed class TypedDynamicExpression1 : DynamicExpression1 {
252 private readonly Type _retType;
254 internal TypedDynamicExpression1(Type retType, Type delegateType, CallSiteBinder binder, Expression arg0)
255 : base(delegateType, binder, arg0) {
259 public sealed override Type Type {
260 get { return _retType; }
264 internal class DynamicExpression2 : DynamicExpression, IArgumentProvider {
265 private object _arg0; // storage for the 1st argument or a readonly collection. See IArgumentProvider for more info.
266 private readonly Expression _arg1; // storage for the 2nd argument
268 internal DynamicExpression2(Type delegateType, CallSiteBinder binder, Expression arg0, Expression arg1)
269 : base(delegateType, binder) {
274 Expression IArgumentProvider.GetArgument(int index) {
276 case 0: return ReturnObject<Expression>(_arg0);
277 case 1: return _arg1;
278 default: throw new InvalidOperationException();
282 int IArgumentProvider.ArgumentCount {
288 internal override ReadOnlyCollection<Expression> GetOrMakeArguments() {
289 return ReturnReadOnly(this, ref _arg0);
292 internal override DynamicExpression Rewrite(Expression[] args) {
293 Debug.Assert(args.Length == 2);
295 return Expression.MakeDynamic(DelegateType, Binder, args[0], args[1]);
299 internal sealed class TypedDynamicExpression2 : DynamicExpression2 {
300 private readonly Type _retType;
302 internal TypedDynamicExpression2(Type retType, Type delegateType, CallSiteBinder binder, Expression arg0, Expression arg1)
303 : base(delegateType, binder, arg0, arg1) {
307 public sealed override Type Type {
308 get { return _retType; }
312 internal class DynamicExpression3 : DynamicExpression, IArgumentProvider {
313 private object _arg0; // storage for the 1st argument or a readonly collection. See IArgumentProvider for more info.
314 private readonly Expression _arg1, _arg2; // storage for the 2nd & 3rd arguments
316 internal DynamicExpression3(Type delegateType, CallSiteBinder binder, Expression arg0, Expression arg1, Expression arg2)
317 : base(delegateType, binder) {
323 Expression IArgumentProvider.GetArgument(int index) {
325 case 0: return ReturnObject<Expression>(_arg0);
326 case 1: return _arg1;
327 case 2: return _arg2;
328 default: throw new InvalidOperationException();
332 int IArgumentProvider.ArgumentCount {
338 internal override ReadOnlyCollection<Expression> GetOrMakeArguments() {
339 return ReturnReadOnly(this, ref _arg0);
342 internal override DynamicExpression Rewrite(Expression[] args) {
343 Debug.Assert(args.Length == 3);
345 return Expression.MakeDynamic(DelegateType, Binder, args[0], args[1], args[2]);
349 internal sealed class TypedDynamicExpression3 : DynamicExpression3 {
350 private readonly Type _retType;
352 internal TypedDynamicExpression3(Type retType, Type delegateType, CallSiteBinder binder, Expression arg0, Expression arg1, Expression arg2)
353 : base(delegateType, binder, arg0, arg1, arg2) {
357 public sealed override Type Type {
358 get { return _retType; }
362 internal class DynamicExpression4 : DynamicExpression, IArgumentProvider {
363 private object _arg0; // storage for the 1st argument or a readonly collection. See IArgumentProvider for more info.
364 private readonly Expression _arg1, _arg2, _arg3; // storage for the 2nd - 4th arguments
366 internal DynamicExpression4(Type delegateType, CallSiteBinder binder, Expression arg0, Expression arg1, Expression arg2, Expression arg3)
367 : base(delegateType, binder) {
374 Expression IArgumentProvider.GetArgument(int index) {
376 case 0: return ReturnObject<Expression>(_arg0);
377 case 1: return _arg1;
378 case 2: return _arg2;
379 case 3: return _arg3;
380 default: throw new InvalidOperationException();
384 int IArgumentProvider.ArgumentCount {
390 internal override ReadOnlyCollection<Expression> GetOrMakeArguments() {
391 return ReturnReadOnly(this, ref _arg0);
394 internal override DynamicExpression Rewrite(Expression[] args) {
395 Debug.Assert(args.Length == 4);
397 return Expression.MakeDynamic(DelegateType, Binder, args[0], args[1], args[2], args[3]);
401 internal sealed class TypedDynamicExpression4 : DynamicExpression4 {
402 private readonly Type _retType;
404 internal TypedDynamicExpression4(Type retType, Type delegateType, CallSiteBinder binder, Expression arg0, Expression arg1, Expression arg2, Expression arg3)
405 : base(delegateType, binder, arg0, arg1, arg2, arg3) {
409 public sealed override Type Type {
410 get { return _retType; }
416 public partial class Expression {
419 /// Creates a <see cref="DynamicExpression" /> that represents a dynamic operation bound by the provided <see cref="CallSiteBinder" />.
421 /// <param name="delegateType">The type of the delegate used by the <see cref="CallSite" />.</param>
422 /// <param name="binder">The runtime binder for the dynamic operation.</param>
423 /// <param name="arguments">The arguments to the dynamic operation.</param>
425 /// A <see cref="DynamicExpression" /> that has <see cref="NodeType" /> equal to
426 /// <see cref="ExpressionType.Dynamic">Dynamic</see> and has the
427 /// <see cref="DynamicExpression.DelegateType">DelegateType</see>,
428 /// <see cref="DynamicExpression.Binder">Binder</see>, and
429 /// <see cref="DynamicExpression.Arguments">Arguments</see> set to the specified values.
431 public static DynamicExpression MakeDynamic(Type delegateType, CallSiteBinder binder, params Expression[] arguments) {
432 return MakeDynamic(delegateType, binder, (IEnumerable<Expression>)arguments);
436 /// Creates a <see cref="DynamicExpression" /> that represents a dynamic operation bound by the provided <see cref="CallSiteBinder" />.
438 /// <param name="delegateType">The type of the delegate used by the <see cref="CallSite" />.</param>
439 /// <param name="binder">The runtime binder for the dynamic operation.</param>
440 /// <param name="arguments">The arguments to the dynamic operation.</param>
442 /// A <see cref="DynamicExpression" /> that has <see cref="NodeType" /> equal to
443 /// <see cref="ExpressionType.Dynamic">Dynamic</see> and has the
444 /// <see cref="DynamicExpression.DelegateType">DelegateType</see>,
445 /// <see cref="DynamicExpression.Binder">Binder</see>, and
446 /// <see cref="DynamicExpression.Arguments">Arguments</see> set to the specified values.
448 public static DynamicExpression MakeDynamic(Type delegateType, CallSiteBinder binder, IEnumerable<Expression> arguments) {
449 ContractUtils.RequiresNotNull(delegateType, "delegateType");
450 ContractUtils.RequiresNotNull(binder, "binder");
451 if (!delegateType.IsSubclassOf(typeof(MulticastDelegate))) throw Error.TypeMustBeDerivedFromSystemDelegate();
453 var method = GetValidMethodForDynamic(delegateType);
455 var args = arguments.ToReadOnly();
456 ValidateArgumentTypes(method, ExpressionType.Dynamic, ref args);
458 return DynamicExpression.Make(method.GetReturnType(), delegateType, binder, args);
462 /// Creates a <see cref="DynamicExpression" /> that represents a dynamic operation bound by the provided <see cref="CallSiteBinder" /> and one argument.
464 /// <param name="delegateType">The type of the delegate used by the <see cref="CallSite" />.</param>
465 /// <param name="binder">The runtime binder for the dynamic operation.</param>
466 /// <param name="arg0">The argument to the dynamic operation.</param>
468 /// A <see cref="DynamicExpression" /> that has <see cref="NodeType" /> equal to
469 /// <see cref="ExpressionType.Dynamic">Dynamic</see> and has the
470 /// <see cref="DynamicExpression.DelegateType">DelegateType</see>,
471 /// <see cref="DynamicExpression.Binder">Binder</see>, and
472 /// <see cref="DynamicExpression.Arguments">Arguments</see> set to the specified values.
474 public static DynamicExpression MakeDynamic(Type delegateType, CallSiteBinder binder, Expression arg0) {
475 ContractUtils.RequiresNotNull(delegateType, "delegateType");
476 ContractUtils.RequiresNotNull(binder, "binder");
477 if (!delegateType.IsSubclassOf(typeof(MulticastDelegate))) throw Error.TypeMustBeDerivedFromSystemDelegate();
479 var method = GetValidMethodForDynamic(delegateType);
480 var parameters = method.GetParametersCached();
482 ValidateArgumentCount(method, ExpressionType.Dynamic, 2, parameters);
483 ValidateDynamicArgument(arg0);
484 ValidateOneArgument(method, ExpressionType.Dynamic, arg0, parameters[1]);
486 return DynamicExpression.Make(method.GetReturnType(), delegateType, binder, arg0);
490 /// Creates a <see cref="DynamicExpression" /> that represents a dynamic operation bound by the provided <see cref="CallSiteBinder" /> and two arguments.
492 /// <param name="delegateType">The type of the delegate used by the <see cref="CallSite" />.</param>
493 /// <param name="binder">The runtime binder for the dynamic operation.</param>
494 /// <param name="arg0">The first argument to the dynamic operation.</param>
495 /// <param name="arg1">The second argument to the dynamic operation.</param>
497 /// A <see cref="DynamicExpression" /> that has <see cref="NodeType" /> equal to
498 /// <see cref="ExpressionType.Dynamic">Dynamic</see> and has the
499 /// <see cref="DynamicExpression.DelegateType">DelegateType</see>,
500 /// <see cref="DynamicExpression.Binder">Binder</see>, and
501 /// <see cref="DynamicExpression.Arguments">Arguments</see> set to the specified values.
503 public static DynamicExpression MakeDynamic(Type delegateType, CallSiteBinder binder, Expression arg0, Expression arg1) {
504 ContractUtils.RequiresNotNull(delegateType, "delegateType");
505 ContractUtils.RequiresNotNull(binder, "binder");
506 if (!delegateType.IsSubclassOf(typeof(MulticastDelegate))) throw Error.TypeMustBeDerivedFromSystemDelegate();
508 var method = GetValidMethodForDynamic(delegateType);
509 var parameters = method.GetParametersCached();
511 ValidateArgumentCount(method, ExpressionType.Dynamic, 3, parameters);
512 ValidateDynamicArgument(arg0);
513 ValidateOneArgument(method, ExpressionType.Dynamic, arg0, parameters[1]);
514 ValidateDynamicArgument(arg1);
515 ValidateOneArgument(method, ExpressionType.Dynamic, arg1, parameters[2]);
517 return DynamicExpression.Make(method.GetReturnType(), delegateType, binder, arg0, arg1);
521 /// Creates a <see cref="DynamicExpression" /> that represents a dynamic operation bound by the provided <see cref="CallSiteBinder" /> and three arguments.
523 /// <param name="delegateType">The type of the delegate used by the <see cref="CallSite" />.</param>
524 /// <param name="binder">The runtime binder for the dynamic operation.</param>
525 /// <param name="arg0">The first argument to the dynamic operation.</param>
526 /// <param name="arg1">The second argument to the dynamic operation.</param>
527 /// <param name="arg2">The third argument to the dynamic operation.</param>
529 /// A <see cref="DynamicExpression" /> that has <see cref="NodeType" /> equal to
530 /// <see cref="ExpressionType.Dynamic">Dynamic</see> and has the
531 /// <see cref="DynamicExpression.DelegateType">DelegateType</see>,
532 /// <see cref="DynamicExpression.Binder">Binder</see>, and
533 /// <see cref="DynamicExpression.Arguments">Arguments</see> set to the specified values.
535 public static DynamicExpression MakeDynamic(Type delegateType, CallSiteBinder binder, Expression arg0, Expression arg1, Expression arg2) {
536 ContractUtils.RequiresNotNull(delegateType, "delegateType");
537 ContractUtils.RequiresNotNull(binder, "binder");
538 if (!delegateType.IsSubclassOf(typeof(MulticastDelegate))) throw Error.TypeMustBeDerivedFromSystemDelegate();
540 var method = GetValidMethodForDynamic(delegateType);
541 var parameters = method.GetParametersCached();
543 ValidateArgumentCount(method, ExpressionType.Dynamic, 4, parameters);
544 ValidateDynamicArgument(arg0);
545 ValidateOneArgument(method, ExpressionType.Dynamic, arg0, parameters[1]);
546 ValidateDynamicArgument(arg1);
547 ValidateOneArgument(method, ExpressionType.Dynamic, arg1, parameters[2]);
548 ValidateDynamicArgument(arg2);
549 ValidateOneArgument(method, ExpressionType.Dynamic, arg2, parameters[3]);
551 return DynamicExpression.Make(method.GetReturnType(), delegateType, binder, arg0, arg1, arg2);
555 /// Creates a <see cref="DynamicExpression" /> that represents a dynamic operation bound by the provided <see cref="CallSiteBinder" /> and four arguments.
557 /// <param name="delegateType">The type of the delegate used by the <see cref="CallSite" />.</param>
558 /// <param name="binder">The runtime binder for the dynamic operation.</param>
559 /// <param name="arg0">The first argument to the dynamic operation.</param>
560 /// <param name="arg1">The second argument to the dynamic operation.</param>
561 /// <param name="arg2">The third argument to the dynamic operation.</param>
562 /// <param name="arg3">The fourth argument to the dynamic operation.</param>
564 /// A <see cref="DynamicExpression" /> that has <see cref="NodeType" /> equal to
565 /// <see cref="ExpressionType.Dynamic">Dynamic</see> and has the
566 /// <see cref="DynamicExpression.DelegateType">DelegateType</see>,
567 /// <see cref="DynamicExpression.Binder">Binder</see>, and
568 /// <see cref="DynamicExpression.Arguments">Arguments</see> set to the specified values.
570 public static DynamicExpression MakeDynamic(Type delegateType, CallSiteBinder binder, Expression arg0, Expression arg1, Expression arg2, Expression arg3) {
571 ContractUtils.RequiresNotNull(delegateType, "delegateType");
572 ContractUtils.RequiresNotNull(binder, "binder");
573 if (!delegateType.IsSubclassOf(typeof(MulticastDelegate))) throw Error.TypeMustBeDerivedFromSystemDelegate();
575 var method = GetValidMethodForDynamic(delegateType);
576 var parameters = method.GetParametersCached();
578 ValidateArgumentCount(method, ExpressionType.Dynamic, 5, parameters);
579 ValidateDynamicArgument(arg0);
580 ValidateOneArgument(method, ExpressionType.Dynamic, arg0, parameters[1]);
581 ValidateDynamicArgument(arg1);
582 ValidateOneArgument(method, ExpressionType.Dynamic, arg1, parameters[2]);
583 ValidateDynamicArgument(arg2);
584 ValidateOneArgument(method, ExpressionType.Dynamic, arg2, parameters[3]);
585 ValidateDynamicArgument(arg3);
586 ValidateOneArgument(method, ExpressionType.Dynamic, arg3, parameters[4]);
588 return DynamicExpression.Make(method.GetReturnType(), delegateType, binder, arg0, arg1, arg2, arg3);
591 private static MethodInfo GetValidMethodForDynamic(Type delegateType) {
592 var method = delegateType.GetMethod("Invoke");
593 var pi = method.GetParametersCached();
594 if (pi.Length == 0 || pi[0].ParameterType != typeof(CallSite)) throw Error.FirstArgumentMustBeCallSite();
599 /// Creates a <see cref="DynamicExpression" /> that represents a dynamic operation bound by the provided <see cref="CallSiteBinder" />.
601 /// <param name="binder">The runtime binder for the dynamic operation.</param>
602 /// <param name="returnType">The result type of the dynamic expression.</param>
603 /// <param name="arguments">The arguments to the dynamic operation.</param>
605 /// A <see cref="DynamicExpression" /> that has <see cref="NodeType" /> equal to
606 /// <see cref="ExpressionType.Dynamic">Dynamic</see> and has the
607 /// <see cref="DynamicExpression.Binder">Binder</see> and
608 /// <see cref="DynamicExpression.Arguments">Arguments</see> set to the specified values.
611 /// The <see cref="DynamicExpression.DelegateType">DelegateType</see> property of the
612 /// result will be inferred from the types of the arguments and the specified return type.
614 public static DynamicExpression Dynamic(CallSiteBinder binder, Type returnType, params Expression[] arguments) {
615 return Dynamic(binder, returnType, (IEnumerable<Expression>)arguments);
619 /// Creates a <see cref="DynamicExpression" /> that represents a dynamic operation bound by the provided <see cref="CallSiteBinder" />.
621 /// <param name="binder">The runtime binder for the dynamic operation.</param>
622 /// <param name="returnType">The result type of the dynamic expression.</param>
623 /// <param name="arg0">The first argument to the dynamic operation.</param>
625 /// A <see cref="DynamicExpression" /> that has <see cref="NodeType" /> equal to
626 /// <see cref="ExpressionType.Dynamic">Dynamic</see> and has the
627 /// <see cref="DynamicExpression.Binder">Binder</see> and
628 /// <see cref="DynamicExpression.Arguments">Arguments</see> set to the specified values.
631 /// The <see cref="DynamicExpression.DelegateType">DelegateType</see> property of the
632 /// result will be inferred from the types of the arguments and the specified return type.
634 public static DynamicExpression Dynamic(CallSiteBinder binder, Type returnType, Expression arg0) {
635 ContractUtils.RequiresNotNull(binder, "binder");
636 ValidateDynamicArgument(arg0);
638 DelegateHelpers.TypeInfo info = DelegateHelpers.GetNextTypeInfo(
640 DelegateHelpers.GetNextTypeInfo(
642 DelegateHelpers.NextTypeInfo(typeof(CallSite))
646 Type delegateType = info.DelegateType;
647 if (delegateType == null) {
648 delegateType = info.MakeDelegateType(returnType, arg0);
651 return DynamicExpression.Make(returnType, delegateType, binder, arg0);
655 /// Creates a <see cref="DynamicExpression" /> that represents a dynamic operation bound by the provided <see cref="CallSiteBinder" />.
657 /// <param name="binder">The runtime binder for the dynamic operation.</param>
658 /// <param name="returnType">The result type of the dynamic expression.</param>
659 /// <param name="arg0">The first argument to the dynamic operation.</param>
660 /// <param name="arg1">The second argument to the dynamic operation.</param>
662 /// A <see cref="DynamicExpression" /> that has <see cref="NodeType" /> equal to
663 /// <see cref="ExpressionType.Dynamic">Dynamic</see> and has the
664 /// <see cref="DynamicExpression.Binder">Binder</see> and
665 /// <see cref="DynamicExpression.Arguments">Arguments</see> set to the specified values.
668 /// The <see cref="DynamicExpression.DelegateType">DelegateType</see> property of the
669 /// result will be inferred from the types of the arguments and the specified return type.
671 public static DynamicExpression Dynamic(CallSiteBinder binder, Type returnType, Expression arg0, Expression arg1) {
672 ContractUtils.RequiresNotNull(binder, "binder");
673 ValidateDynamicArgument(arg0);
674 ValidateDynamicArgument(arg1);
676 DelegateHelpers.TypeInfo info = DelegateHelpers.GetNextTypeInfo(
678 DelegateHelpers.GetNextTypeInfo(
680 DelegateHelpers.GetNextTypeInfo(
682 DelegateHelpers.NextTypeInfo(typeof(CallSite))
687 Type delegateType = info.DelegateType;
688 if (delegateType == null) {
689 delegateType = info.MakeDelegateType(returnType, arg0, arg1);
692 return DynamicExpression.Make(returnType, delegateType, binder, arg0, arg1);
696 /// Creates a <see cref="DynamicExpression" /> that represents a dynamic operation bound by the provided <see cref="CallSiteBinder" />.
698 /// <param name="binder">The runtime binder for the dynamic operation.</param>
699 /// <param name="returnType">The result type of the dynamic expression.</param>
700 /// <param name="arg0">The first argument to the dynamic operation.</param>
701 /// <param name="arg1">The second argument to the dynamic operation.</param>
702 /// <param name="arg2">The third argument to the dynamic operation.</param>
704 /// A <see cref="DynamicExpression" /> that has <see cref="NodeType" /> equal to
705 /// <see cref="ExpressionType.Dynamic">Dynamic</see> and has the
706 /// <see cref="DynamicExpression.Binder">Binder</see> and
707 /// <see cref="DynamicExpression.Arguments">Arguments</see> set to the specified values.
710 /// The <see cref="DynamicExpression.DelegateType">DelegateType</see> property of the
711 /// result will be inferred from the types of the arguments and the specified return type.
713 public static DynamicExpression Dynamic(CallSiteBinder binder, Type returnType, Expression arg0, Expression arg1, Expression arg2) {
714 ContractUtils.RequiresNotNull(binder, "binder");
715 ValidateDynamicArgument(arg0);
716 ValidateDynamicArgument(arg1);
717 ValidateDynamicArgument(arg2);
719 DelegateHelpers.TypeInfo info = DelegateHelpers.GetNextTypeInfo(
721 DelegateHelpers.GetNextTypeInfo(
723 DelegateHelpers.GetNextTypeInfo(
725 DelegateHelpers.GetNextTypeInfo(
727 DelegateHelpers.NextTypeInfo(typeof(CallSite))
733 Type delegateType = info.DelegateType;
734 if (delegateType == null) {
735 delegateType = info.MakeDelegateType(returnType, arg0, arg1, arg2);
738 return DynamicExpression.Make(returnType, delegateType, binder, arg0, arg1, arg2);
742 /// Creates a <see cref="DynamicExpression" /> that represents a dynamic operation bound by the provided <see cref="CallSiteBinder" />.
744 /// <param name="binder">The runtime binder for the dynamic operation.</param>
745 /// <param name="returnType">The result type of the dynamic expression.</param>
746 /// <param name="arg0">The first argument to the dynamic operation.</param>
747 /// <param name="arg1">The second argument to the dynamic operation.</param>
748 /// <param name="arg2">The third argument to the dynamic operation.</param>
749 /// <param name="arg3">The fourth argument to the dynamic operation.</param>
751 /// A <see cref="DynamicExpression" /> that has <see cref="NodeType" /> equal to
752 /// <see cref="ExpressionType.Dynamic">Dynamic</see> and has the
753 /// <see cref="DynamicExpression.Binder">Binder</see> and
754 /// <see cref="DynamicExpression.Arguments">Arguments</see> set to the specified values.
757 /// The <see cref="DynamicExpression.DelegateType">DelegateType</see> property of the
758 /// result will be inferred from the types of the arguments and the specified return type.
760 public static DynamicExpression Dynamic(CallSiteBinder binder, Type returnType, Expression arg0, Expression arg1, Expression arg2, Expression arg3) {
761 ContractUtils.RequiresNotNull(binder, "binder");
762 ValidateDynamicArgument(arg0);
763 ValidateDynamicArgument(arg1);
764 ValidateDynamicArgument(arg2);
765 ValidateDynamicArgument(arg3);
767 DelegateHelpers.TypeInfo info = DelegateHelpers.GetNextTypeInfo(
769 DelegateHelpers.GetNextTypeInfo(
771 DelegateHelpers.GetNextTypeInfo(
773 DelegateHelpers.GetNextTypeInfo(
775 DelegateHelpers.GetNextTypeInfo(
777 DelegateHelpers.NextTypeInfo(typeof(CallSite))
784 Type delegateType = info.DelegateType;
785 if (delegateType == null) {
786 delegateType = info.MakeDelegateType(returnType, arg0, arg1, arg2, arg3);
789 return DynamicExpression.Make(returnType, delegateType, binder, arg0, arg1, arg2, arg3);
793 /// Creates a <see cref="DynamicExpression" /> that represents a dynamic operation bound by the provided <see cref="CallSiteBinder" />.
795 /// <param name="binder">The runtime binder for the dynamic operation.</param>
796 /// <param name="returnType">The result type of the dynamic expression.</param>
797 /// <param name="arguments">The arguments to the dynamic operation.</param>
799 /// A <see cref="DynamicExpression" /> that has <see cref="NodeType" /> equal to
800 /// <see cref="ExpressionType.Dynamic">Dynamic</see> and has the
801 /// <see cref="DynamicExpression.Binder">Binder</see> and
802 /// <see cref="DynamicExpression.Arguments">Arguments</see> set to the specified values.
805 /// The <see cref="DynamicExpression.DelegateType">DelegateType</see> property of the
806 /// result will be inferred from the types of the arguments and the specified return type.
808 public static DynamicExpression Dynamic(CallSiteBinder binder, Type returnType, IEnumerable<Expression> arguments) {
809 ContractUtils.RequiresNotNull(arguments, "arguments");
810 ContractUtils.RequiresNotNull(returnType, "returnType");
812 var args = arguments.ToReadOnly();
813 ContractUtils.RequiresNotEmpty(args, "args");
814 return MakeDynamic(binder, returnType, args);
817 private static DynamicExpression MakeDynamic(CallSiteBinder binder, Type returnType, ReadOnlyCollection<Expression> args) {
818 ContractUtils.RequiresNotNull(binder, "binder");
820 for (int i = 0; i < args.Count; i++) {
821 Expression arg = args[i];
823 ValidateDynamicArgument(arg);
826 Type delegateType = DelegateHelpers.MakeCallSiteDelegate(args, returnType);
828 // Since we made a delegate with argument types that exactly match,
829 // we can skip delegate and argument validation
831 switch (args.Count) {
832 case 1: return DynamicExpression.Make(returnType, delegateType, binder, args[0]);
833 case 2: return DynamicExpression.Make(returnType, delegateType, binder, args[0], args[1]);
834 case 3: return DynamicExpression.Make(returnType, delegateType, binder, args[0], args[1], args[2]);
835 case 4: return DynamicExpression.Make(returnType, delegateType, binder, args[0], args[1], args[2], args[3]);
836 default: return DynamicExpression.Make(returnType, delegateType, binder, args);
840 private static void ValidateDynamicArgument(Expression arg) {
841 RequiresCanRead(arg, "arguments");
843 ContractUtils.RequiresNotNull(type, "type");
844 TypeUtils.ValidateType(type);
845 if (type == typeof(void)) throw Error.ArgumentTypeCannotBeVoid();