Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / Core / Microsoft / Scripting / Ast / DynamicExpression.cs / 1305376 / DynamicExpression.cs
/* ****************************************************************************
*
* Copyright (c) Microsoft Corporation.
*
* This source code is subject to terms and conditions of the Microsoft Public License. A
* copy of the license can be found in the License.html file at the root of this distribution. If
* you cannot locate the Microsoft Public License, please send an email to
* dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
* by the terms of the Microsoft Public License.
*
* You must not remove this notice, or any other, from this software.
*
*
* ***************************************************************************/
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Dynamic.Utils;
using System.Linq.Expressions.Compiler;
using System.Reflection;
using System.Runtime.CompilerServices;
#if SILVERLIGHT
using System.Core;
#endif
namespace System.Linq.Expressions {
///
/// Represents a dynamic operation.
///
#if !SILVERLIGHT
[DebuggerTypeProxy(typeof(Expression.DynamicExpressionProxy))]
#endif
public class DynamicExpression : Expression, IArgumentProvider {
private readonly CallSiteBinder _binder;
private readonly Type _delegateType;
internal DynamicExpression(Type delegateType, CallSiteBinder binder) {
Debug.Assert(delegateType.GetMethod("Invoke").GetReturnType() == typeof(object) || GetType() != typeof(DynamicExpression));
_delegateType = delegateType;
_binder = binder;
}
internal static DynamicExpression Make(Type returnType, Type delegateType, CallSiteBinder binder, ReadOnlyCollection arguments) {
if (returnType == typeof(object)) {
return new DynamicExpressionN(delegateType, binder, arguments);
} else {
return new TypedDynamicExpressionN(returnType, delegateType, binder, arguments);
}
}
internal static DynamicExpression Make(Type returnType, Type delegateType, CallSiteBinder binder, Expression arg0) {
if (returnType == typeof(object)) {
return new DynamicExpression1(delegateType, binder, arg0);
} else {
return new TypedDynamicExpression1(returnType, delegateType, binder, arg0);
}
}
internal static DynamicExpression Make(Type returnType, Type delegateType, CallSiteBinder binder, Expression arg0, Expression arg1) {
if (returnType == typeof(object)) {
return new DynamicExpression2(delegateType, binder, arg0, arg1);
} else {
return new TypedDynamicExpression2(returnType, delegateType, binder, arg0, arg1);
}
}
internal static DynamicExpression Make(Type returnType, Type delegateType, CallSiteBinder binder, Expression arg0, Expression arg1, Expression arg2) {
if (returnType == typeof(object)) {
return new DynamicExpression3(delegateType, binder, arg0, arg1, arg2);
} else {
return new TypedDynamicExpression3(returnType, delegateType, binder, arg0, arg1, arg2);
}
}
internal static DynamicExpression Make(Type returnType, Type delegateType, CallSiteBinder binder, Expression arg0, Expression arg1, Expression arg2, Expression arg3) {
if (returnType == typeof(object)) {
return new DynamicExpression4(delegateType, binder, arg0, arg1, arg2, arg3);
} else {
return new TypedDynamicExpression4(returnType, delegateType, binder, arg0, arg1, arg2, arg3);
}
}
///
/// Gets the static type of the expression that this represents.
///
/// The that represents the static type of the expression.
public override Type Type {
get { return typeof(object); }
}
///
/// Returns the node type of this Expression. Extension nodes should return
/// ExpressionType.Extension when overriding this method.
///
/// The of the expression.
public sealed override ExpressionType NodeType {
get { return ExpressionType.Dynamic; }
}
///
/// Gets the , which determines the runtime behavior of the
/// dynamic site.
///
public CallSiteBinder Binder {
get { return _binder; }
}
///
/// Gets the type of the delegate used by the .
///
public Type DelegateType {
get { return _delegateType; }
}
///
/// Gets the arguments to the dynamic operation.
///
public ReadOnlyCollection Arguments {
get { return GetOrMakeArguments(); }
}
internal virtual ReadOnlyCollection GetOrMakeArguments() {
throw ContractUtils.Unreachable;
}
///
/// Dispatches to the specific visit method for this node type.
///
protected internal override Expression Accept(ExpressionVisitor visitor) {
return visitor.VisitDynamic(this);
}
///
/// Makes a copy of this node replacing the args with the provided values. The
/// number of the args needs to match the number of the current block.
///
/// This helper is provided to allow re-writing of nodes to not depend on the specific optimized
/// subclass of DynamicExpression which is being used.
///
internal virtual DynamicExpression Rewrite(Expression[] args) {
throw ContractUtils.Unreachable;
}
///
/// Creates a new expression that is like this one, but using the
/// supplied children. If all of the children are the same, it will
/// return this expression.
///
/// The property of the result.
/// This expression if no children changed, or an expression with the updated children.
public DynamicExpression Update(IEnumerable arguments) {
if (arguments == Arguments) {
return this;
}
return Expression.MakeDynamic(DelegateType, Binder, arguments);
}
#region IArgumentProvider Members
Expression IArgumentProvider.GetArgument(int index) {
throw ContractUtils.Unreachable;
}
int IArgumentProvider.ArgumentCount {
get { throw ContractUtils.Unreachable; }
}
#endregion
}
#region Specialized Subclasses
internal class DynamicExpressionN : DynamicExpression, IArgumentProvider {
private IList _arguments; // storage for the original IList or readonly collection. See IArgumentProvider for more info.
internal DynamicExpressionN(Type delegateType, CallSiteBinder binder, IList arguments)
: base(delegateType, binder) {
_arguments = arguments;
}
Expression IArgumentProvider.GetArgument(int index) {
return _arguments[index];
}
int IArgumentProvider.ArgumentCount {
get {
return _arguments.Count;
}
}
internal override ReadOnlyCollection GetOrMakeArguments() {
return ReturnReadOnly(ref _arguments);
}
internal override DynamicExpression Rewrite(Expression[] args) {
Debug.Assert(args.Length == ((IArgumentProvider)this).ArgumentCount);
return Expression.MakeDynamic(DelegateType, Binder, args);
}
}
internal class TypedDynamicExpressionN : DynamicExpressionN {
private readonly Type _returnType;
internal TypedDynamicExpressionN(Type returnType, Type delegateType, CallSiteBinder binder, IList arguments)
: base(delegateType, binder, arguments) {
Debug.Assert(delegateType.GetMethod("Invoke").GetReturnType() == returnType);
_returnType = returnType;
}
public sealed override Type Type {
get { return _returnType; }
}
}
internal class DynamicExpression1 : DynamicExpression, IArgumentProvider {
private object _arg0; // storage for the 1st argument or a readonly collection. See IArgumentProvider for more info.
internal DynamicExpression1(Type delegateType, CallSiteBinder binder, Expression arg0)
: base(delegateType, binder) {
_arg0 = arg0;
}
Expression IArgumentProvider.GetArgument(int index) {
switch (index) {
case 0: return ReturnObject(_arg0);
default: throw new InvalidOperationException();
}
}
int IArgumentProvider.ArgumentCount {
get {
return 1;
}
}
internal override ReadOnlyCollection GetOrMakeArguments() {
return ReturnReadOnly(this, ref _arg0);
}
internal override DynamicExpression Rewrite(Expression[] args) {
Debug.Assert(args.Length == 1);
return Expression.MakeDynamic(DelegateType, Binder, args[0]);
}
}
internal sealed class TypedDynamicExpression1 : DynamicExpression1 {
private readonly Type _retType;
internal TypedDynamicExpression1(Type retType, Type delegateType, CallSiteBinder binder, Expression arg0)
: base(delegateType, binder, arg0) {
_retType = retType;
}
public sealed override Type Type {
get { return _retType; }
}
}
internal class DynamicExpression2 : DynamicExpression, IArgumentProvider {
private object _arg0; // storage for the 1st argument or a readonly collection. See IArgumentProvider for more info.
private readonly Expression _arg1; // storage for the 2nd argument
internal DynamicExpression2(Type delegateType, CallSiteBinder binder, Expression arg0, Expression arg1)
: base(delegateType, binder) {
_arg0 = arg0;
_arg1 = arg1;
}
Expression IArgumentProvider.GetArgument(int index) {
switch (index) {
case 0: return ReturnObject(_arg0);
case 1: return _arg1;
default: throw new InvalidOperationException();
}
}
int IArgumentProvider.ArgumentCount {
get {
return 2;
}
}
internal override ReadOnlyCollection GetOrMakeArguments() {
return ReturnReadOnly(this, ref _arg0);
}
internal override DynamicExpression Rewrite(Expression[] args) {
Debug.Assert(args.Length == 2);
return Expression.MakeDynamic(DelegateType, Binder, args[0], args[1]);
}
}
internal sealed class TypedDynamicExpression2 : DynamicExpression2 {
private readonly Type _retType;
internal TypedDynamicExpression2(Type retType, Type delegateType, CallSiteBinder binder, Expression arg0, Expression arg1)
: base(delegateType, binder, arg0, arg1) {
_retType = retType;
}
public sealed override Type Type {
get { return _retType; }
}
}
internal class DynamicExpression3 : DynamicExpression, IArgumentProvider {
private object _arg0; // storage for the 1st argument or a readonly collection. See IArgumentProvider for more info.
private readonly Expression _arg1, _arg2; // storage for the 2nd & 3rd arguments
internal DynamicExpression3(Type delegateType, CallSiteBinder binder, Expression arg0, Expression arg1, Expression arg2)
: base(delegateType, binder) {
_arg0 = arg0;
_arg1 = arg1;
_arg2 = arg2;
}
Expression IArgumentProvider.GetArgument(int index) {
switch (index) {
case 0: return ReturnObject(_arg0);
case 1: return _arg1;
case 2: return _arg2;
default: throw new InvalidOperationException();
}
}
int IArgumentProvider.ArgumentCount {
get {
return 3;
}
}
internal override ReadOnlyCollection GetOrMakeArguments() {
return ReturnReadOnly(this, ref _arg0);
}
internal override DynamicExpression Rewrite(Expression[] args) {
Debug.Assert(args.Length == 3);
return Expression.MakeDynamic(DelegateType, Binder, args[0], args[1], args[2]);
}
}
internal sealed class TypedDynamicExpression3 : DynamicExpression3 {
private readonly Type _retType;
internal TypedDynamicExpression3(Type retType, Type delegateType, CallSiteBinder binder, Expression arg0, Expression arg1, Expression arg2)
: base(delegateType, binder, arg0, arg1, arg2) {
_retType = retType;
}
public sealed override Type Type {
get { return _retType; }
}
}
internal class DynamicExpression4 : DynamicExpression, IArgumentProvider {
private object _arg0; // storage for the 1st argument or a readonly collection. See IArgumentProvider for more info.
private readonly Expression _arg1, _arg2, _arg3; // storage for the 2nd - 4th arguments
internal DynamicExpression4(Type delegateType, CallSiteBinder binder, Expression arg0, Expression arg1, Expression arg2, Expression arg3)
: base(delegateType, binder) {
_arg0 = arg0;
_arg1 = arg1;
_arg2 = arg2;
_arg3 = arg3;
}
Expression IArgumentProvider.GetArgument(int index) {
switch (index) {
case 0: return ReturnObject(_arg0);
case 1: return _arg1;
case 2: return _arg2;
case 3: return _arg3;
default: throw new InvalidOperationException();
}
}
int IArgumentProvider.ArgumentCount {
get {
return 4;
}
}
internal override ReadOnlyCollection GetOrMakeArguments() {
return ReturnReadOnly(this, ref _arg0);
}
internal override DynamicExpression Rewrite(Expression[] args) {
Debug.Assert(args.Length == 4);
return Expression.MakeDynamic(DelegateType, Binder, args[0], args[1], args[2], args[3]);
}
}
internal sealed class TypedDynamicExpression4 : DynamicExpression4 {
private readonly Type _retType;
internal TypedDynamicExpression4(Type retType, Type delegateType, CallSiteBinder binder, Expression arg0, Expression arg1, Expression arg2, Expression arg3)
: base(delegateType, binder, arg0, arg1, arg2, arg3) {
_retType = retType;
}
public sealed override Type Type {
get { return _retType; }
}
}
#endregion
public partial class Expression {
///
/// Creates a that represents a dynamic operation bound by the provided .
///
/// The type of the delegate used by the .
/// The runtime binder for the dynamic operation.
/// The arguments to the dynamic operation.
///
/// A that has equal to
/// Dynamic and has the
/// DelegateType ,
/// Binder , and
/// Arguments set to the specified values.
///
public static DynamicExpression MakeDynamic(Type delegateType, CallSiteBinder binder, params Expression[] arguments) {
return MakeDynamic(delegateType, binder, (IEnumerable)arguments);
}
///
/// Creates a that represents a dynamic operation bound by the provided .
///
/// The type of the delegate used by the .
/// The runtime binder for the dynamic operation.
/// The arguments to the dynamic operation.
///
/// A that has equal to
/// Dynamic and has the
/// DelegateType ,
/// Binder , and
/// Arguments set to the specified values.
///
public static DynamicExpression MakeDynamic(Type delegateType, CallSiteBinder binder, IEnumerable arguments) {
ContractUtils.RequiresNotNull(delegateType, "delegateType");
ContractUtils.RequiresNotNull(binder, "binder");
if (!delegateType.IsSubclassOf(typeof(Delegate))) throw Error.TypeMustBeDerivedFromSystemDelegate();
var method = GetValidMethodForDynamic(delegateType);
var args = arguments.ToReadOnly();
ValidateArgumentTypes(method, ExpressionType.Dynamic, ref args);
return DynamicExpression.Make(method.GetReturnType(), delegateType, binder, args);
}
///
/// Creates a that represents a dynamic operation bound by the provided and one argument.
///
/// The type of the delegate used by the .
/// The runtime binder for the dynamic operation.
/// The argument to the dynamic operation.
///
/// A that has equal to
/// Dynamic and has the
/// DelegateType ,
/// Binder , and
/// Arguments set to the specified values.
///
public static DynamicExpression MakeDynamic(Type delegateType, CallSiteBinder binder, Expression arg0) {
ContractUtils.RequiresNotNull(delegateType, "delegatType");
ContractUtils.RequiresNotNull(binder, "binder");
if (!delegateType.IsSubclassOf(typeof(Delegate))) throw Error.TypeMustBeDerivedFromSystemDelegate();
var method = GetValidMethodForDynamic(delegateType);
var parameters = method.GetParametersCached();
ValidateArgumentCount(method, ExpressionType.Dynamic, 2, parameters);
ValidateDynamicArgument(arg0);
ValidateOneArgument(method, ExpressionType.Dynamic, arg0, parameters[1]);
return DynamicExpression.Make(method.GetReturnType(), delegateType, binder, arg0);
}
///
/// Creates a that represents a dynamic operation bound by the provided and two arguments.
///
/// The type of the delegate used by the .
/// The runtime binder for the dynamic operation.
/// The first argument to the dynamic operation.
/// The second argument to the dynamic operation.
///
/// A that has equal to
/// Dynamic and has the
/// DelegateType ,
/// Binder , and
/// Arguments set to the specified values.
///
public static DynamicExpression MakeDynamic(Type delegateType, CallSiteBinder binder, Expression arg0, Expression arg1) {
ContractUtils.RequiresNotNull(delegateType, "delegatType");
ContractUtils.RequiresNotNull(binder, "binder");
if (!delegateType.IsSubclassOf(typeof(Delegate))) throw Error.TypeMustBeDerivedFromSystemDelegate();
var method = GetValidMethodForDynamic(delegateType);
var parameters = method.GetParametersCached();
ValidateArgumentCount(method, ExpressionType.Dynamic, 3, parameters);
ValidateDynamicArgument(arg0);
ValidateOneArgument(method, ExpressionType.Dynamic, arg0, parameters[1]);
ValidateDynamicArgument(arg1);
ValidateOneArgument(method, ExpressionType.Dynamic, arg1, parameters[2]);
return DynamicExpression.Make(method.GetReturnType(), delegateType, binder, arg0, arg1);
}
///
/// Creates a that represents a dynamic operation bound by the provided and three arguments.
///
/// The type of the delegate used by the .
/// The runtime binder for the dynamic operation.
/// The first argument to the dynamic operation.
/// The second argument to the dynamic operation.
/// The third argument to the dynamic operation.
///
/// A that has equal to
/// Dynamic and has the
/// DelegateType ,
/// Binder , and
/// Arguments set to the specified values.
///
public static DynamicExpression MakeDynamic(Type delegateType, CallSiteBinder binder, Expression arg0, Expression arg1, Expression arg2) {
ContractUtils.RequiresNotNull(delegateType, "delegatType");
ContractUtils.RequiresNotNull(binder, "binder");
if (!delegateType.IsSubclassOf(typeof(Delegate))) throw Error.TypeMustBeDerivedFromSystemDelegate();
var method = GetValidMethodForDynamic(delegateType);
var parameters = method.GetParametersCached();
ValidateArgumentCount(method, ExpressionType.Dynamic, 4, parameters);
ValidateDynamicArgument(arg0);
ValidateOneArgument(method, ExpressionType.Dynamic, arg0, parameters[1]);
ValidateDynamicArgument(arg1);
ValidateOneArgument(method, ExpressionType.Dynamic, arg1, parameters[2]);
ValidateDynamicArgument(arg2);
ValidateOneArgument(method, ExpressionType.Dynamic, arg2, parameters[3]);
return DynamicExpression.Make(method.GetReturnType(), delegateType, binder, arg0, arg1, arg2);
}
///
/// Creates a that represents a dynamic operation bound by the provided and four arguments.
///
/// The type of the delegate used by the .
/// The runtime binder for the dynamic operation.
/// The first argument to the dynamic operation.
/// The second argument to the dynamic operation.
/// The third argument to the dynamic operation.
/// The fourth argument to the dynamic operation.
///
/// A that has equal to
/// Dynamic and has the
/// DelegateType ,
/// Binder , and
/// Arguments set to the specified values.
///
public static DynamicExpression MakeDynamic(Type delegateType, CallSiteBinder binder, Expression arg0, Expression arg1, Expression arg2, Expression arg3) {
ContractUtils.RequiresNotNull(delegateType, "delegatType");
ContractUtils.RequiresNotNull(binder, "binder");
if (!delegateType.IsSubclassOf(typeof(Delegate))) throw Error.TypeMustBeDerivedFromSystemDelegate();
var method = GetValidMethodForDynamic(delegateType);
var parameters = method.GetParametersCached();
ValidateArgumentCount(method, ExpressionType.Dynamic, 5, parameters);
ValidateDynamicArgument(arg0);
ValidateOneArgument(method, ExpressionType.Dynamic, arg0, parameters[1]);
ValidateDynamicArgument(arg1);
ValidateOneArgument(method, ExpressionType.Dynamic, arg1, parameters[2]);
ValidateDynamicArgument(arg2);
ValidateOneArgument(method, ExpressionType.Dynamic, arg2, parameters[3]);
ValidateDynamicArgument(arg3);
ValidateOneArgument(method, ExpressionType.Dynamic, arg3, parameters[4]);
return DynamicExpression.Make(method.GetReturnType(), delegateType, binder, arg0, arg1, arg2, arg3);
}
private static MethodInfo GetValidMethodForDynamic(Type delegateType) {
var method = delegateType.GetMethod("Invoke");
var pi = method.GetParametersCached();
if (pi.Length == 0 || pi[0].ParameterType != typeof(CallSite)) throw Error.FirstArgumentMustBeCallSite();
return method;
}
///
/// Creates a that represents a dynamic operation bound by the provided .
///
/// The runtime binder for the dynamic operation.
/// The result type of the dynamic expression.
/// The arguments to the dynamic operation.
///
/// A that has equal to
/// Dynamic and has the
/// Binder and
/// Arguments set to the specified values.
///
///
/// The DelegateType property of the
/// result will be inferred from the types of the arguments and the specified return type.
///
public static DynamicExpression Dynamic(CallSiteBinder binder, Type returnType, params Expression[] arguments) {
return Dynamic(binder, returnType, (IEnumerable)arguments);
}
///
/// Creates a that represents a dynamic operation bound by the provided .
///
/// The runtime binder for the dynamic operation.
/// The result type of the dynamic expression.
/// The first argument to the dynamic operation.
///
/// A that has equal to
/// Dynamic and has the
/// Binder and
/// Arguments set to the specified values.
///
///
/// The DelegateType property of the
/// result will be inferred from the types of the arguments and the specified return type.
///
public static DynamicExpression Dynamic(CallSiteBinder binder, Type returnType, Expression arg0) {
ContractUtils.RequiresNotNull(binder, "binder");
ValidateDynamicArgument(arg0);
DelegateHelpers.TypeInfo info = DelegateHelpers.GetNextTypeInfo(
returnType,
DelegateHelpers.GetNextTypeInfo(
arg0.Type,
DelegateHelpers.NextTypeInfo(typeof(CallSite))
)
);
Type delegateType = info.DelegateType;
if (delegateType == null) {
delegateType = info.MakeDelegateType(returnType, arg0);
}
return DynamicExpression.Make(returnType, delegateType, binder, arg0);
}
///
/// Creates a that represents a dynamic operation bound by the provided .
///
/// The runtime binder for the dynamic operation.
/// The result type of the dynamic expression.
/// The first argument to the dynamic operation.
/// The second argument to the dynamic operation.
///
/// A that has equal to
/// Dynamic and has the
/// Binder and
/// Arguments set to the specified values.
///
///
/// The DelegateType property of the
/// result will be inferred from the types of the arguments and the specified return type.
///
public static DynamicExpression Dynamic(CallSiteBinder binder, Type returnType, Expression arg0, Expression arg1) {
ContractUtils.RequiresNotNull(binder, "binder");
ValidateDynamicArgument(arg0);
ValidateDynamicArgument(arg1);
DelegateHelpers.TypeInfo info = DelegateHelpers.GetNextTypeInfo(
returnType,
DelegateHelpers.GetNextTypeInfo(
arg1.Type,
DelegateHelpers.GetNextTypeInfo(
arg0.Type,
DelegateHelpers.NextTypeInfo(typeof(CallSite))
)
)
);
Type delegateType = info.DelegateType;
if (delegateType == null) {
delegateType = info.MakeDelegateType(returnType, arg0, arg1);
}
return DynamicExpression.Make(returnType, delegateType, binder, arg0, arg1);
}
///
/// Creates a that represents a dynamic operation bound by the provided .
///
/// The runtime binder for the dynamic operation.
/// The result type of the dynamic expression.
/// The first argument to the dynamic operation.
/// The second argument to the dynamic operation.
/// The third argument to the dynamic operation.
///
/// A that has equal to
/// Dynamic and has the
/// Binder and
/// Arguments set to the specified values.
///
///
/// The DelegateType property of the
/// result will be inferred from the types of the arguments and the specified return type.
///
public static DynamicExpression Dynamic(CallSiteBinder binder, Type returnType, Expression arg0, Expression arg1, Expression arg2) {
ContractUtils.RequiresNotNull(binder, "binder");
ValidateDynamicArgument(arg0);
ValidateDynamicArgument(arg1);
ValidateDynamicArgument(arg2);
DelegateHelpers.TypeInfo info = DelegateHelpers.GetNextTypeInfo(
returnType,
DelegateHelpers.GetNextTypeInfo(
arg2.Type,
DelegateHelpers.GetNextTypeInfo(
arg1.Type,
DelegateHelpers.GetNextTypeInfo(
arg0.Type,
DelegateHelpers.NextTypeInfo(typeof(CallSite))
)
)
)
);
Type delegateType = info.DelegateType;
if (delegateType == null) {
delegateType = info.MakeDelegateType(returnType, arg0, arg1, arg2);
}
return DynamicExpression.Make(returnType, delegateType, binder, arg0, arg1, arg2);
}
///
/// Creates a that represents a dynamic operation bound by the provided .
///
/// The runtime binder for the dynamic operation.
/// The result type of the dynamic expression.
/// The first argument to the dynamic operation.
/// The second argument to the dynamic operation.
/// The third argument to the dynamic operation.
/// The fourth argument to the dynamic operation.
///
/// A that has equal to
/// Dynamic and has the
/// Binder and
/// Arguments set to the specified values.
///
///
/// The DelegateType property of the
/// result will be inferred from the types of the arguments and the specified return type.
///
public static DynamicExpression Dynamic(CallSiteBinder binder, Type returnType, Expression arg0, Expression arg1, Expression arg2, Expression arg3) {
ContractUtils.RequiresNotNull(binder, "binder");
ValidateDynamicArgument(arg0);
ValidateDynamicArgument(arg1);
ValidateDynamicArgument(arg2);
ValidateDynamicArgument(arg3);
DelegateHelpers.TypeInfo info = DelegateHelpers.GetNextTypeInfo(
returnType,
DelegateHelpers.GetNextTypeInfo(
arg3.Type,
DelegateHelpers.GetNextTypeInfo(
arg2.Type,
DelegateHelpers.GetNextTypeInfo(
arg1.Type,
DelegateHelpers.GetNextTypeInfo(
arg0.Type,
DelegateHelpers.NextTypeInfo(typeof(CallSite))
)
)
)
)
);
Type delegateType = info.DelegateType;
if (delegateType == null) {
delegateType = info.MakeDelegateType(returnType, arg0, arg1, arg2, arg3);
}
return DynamicExpression.Make(returnType, delegateType, binder, arg0, arg1, arg2, arg3);
}
///
/// Creates a that represents a dynamic operation bound by the provided .
///
/// The runtime binder for the dynamic operation.
/// The result type of the dynamic expression.
/// The arguments to the dynamic operation.
///
/// A that has equal to
/// Dynamic and has the
/// Binder and
/// Arguments set to the specified values.
///
///
/// The DelegateType property of the
/// result will be inferred from the types of the arguments and the specified return type.
///
public static DynamicExpression Dynamic(CallSiteBinder binder, Type returnType, IEnumerable arguments) {
ContractUtils.RequiresNotNull(arguments, "arguments");
ContractUtils.RequiresNotNull(returnType, "returnType");
var args = arguments.ToReadOnly();
ContractUtils.RequiresNotEmpty(args, "args");
return MakeDynamic(binder, returnType, args);
}
private static DynamicExpression MakeDynamic(CallSiteBinder binder, Type returnType, ReadOnlyCollection args) {
ContractUtils.RequiresNotNull(binder, "binder");
for (int i = 0; i < args.Count; i++) {
Expression arg = args[i];
ValidateDynamicArgument(arg);
}
Type delegateType = DelegateHelpers.MakeCallSiteDelegate(args, returnType);
// Since we made a delegate with argument types that exactly match,
// we can skip delegate and argument validation
switch (args.Count) {
case 1: return DynamicExpression.Make(returnType, delegateType, binder, args[0]);
case 2: return DynamicExpression.Make(returnType, delegateType, binder, args[0], args[1]);
case 3: return DynamicExpression.Make(returnType, delegateType, binder, args[0], args[1], args[2]);
case 4: return DynamicExpression.Make(returnType, delegateType, binder, args[0], args[1], args[2], args[3]);
default: return DynamicExpression.Make(returnType, delegateType, binder, args);
}
}
private static void ValidateDynamicArgument(Expression arg) {
RequiresCanRead(arg, "arguments");
var type = arg.Type;
ContractUtils.RequiresNotNull(type, "type");
TypeUtils.ValidateType(type);
if (type == typeof(void)) throw Error.ArgumentTypeCannotBeVoid();
}
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
/* ****************************************************************************
*
* Copyright (c) Microsoft Corporation.
*
* This source code is subject to terms and conditions of the Microsoft Public License. A
* copy of the license can be found in the License.html file at the root of this distribution. If
* you cannot locate the Microsoft Public License, please send an email to
* dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
* by the terms of the Microsoft Public License.
*
* You must not remove this notice, or any other, from this software.
*
*
* ***************************************************************************/
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Dynamic.Utils;
using System.Linq.Expressions.Compiler;
using System.Reflection;
using System.Runtime.CompilerServices;
#if SILVERLIGHT
using System.Core;
#endif
namespace System.Linq.Expressions {
///
/// Represents a dynamic operation.
///
#if !SILVERLIGHT
[DebuggerTypeProxy(typeof(Expression.DynamicExpressionProxy))]
#endif
public class DynamicExpression : Expression, IArgumentProvider {
private readonly CallSiteBinder _binder;
private readonly Type _delegateType;
internal DynamicExpression(Type delegateType, CallSiteBinder binder) {
Debug.Assert(delegateType.GetMethod("Invoke").GetReturnType() == typeof(object) || GetType() != typeof(DynamicExpression));
_delegateType = delegateType;
_binder = binder;
}
internal static DynamicExpression Make(Type returnType, Type delegateType, CallSiteBinder binder, ReadOnlyCollection arguments) {
if (returnType == typeof(object)) {
return new DynamicExpressionN(delegateType, binder, arguments);
} else {
return new TypedDynamicExpressionN(returnType, delegateType, binder, arguments);
}
}
internal static DynamicExpression Make(Type returnType, Type delegateType, CallSiteBinder binder, Expression arg0) {
if (returnType == typeof(object)) {
return new DynamicExpression1(delegateType, binder, arg0);
} else {
return new TypedDynamicExpression1(returnType, delegateType, binder, arg0);
}
}
internal static DynamicExpression Make(Type returnType, Type delegateType, CallSiteBinder binder, Expression arg0, Expression arg1) {
if (returnType == typeof(object)) {
return new DynamicExpression2(delegateType, binder, arg0, arg1);
} else {
return new TypedDynamicExpression2(returnType, delegateType, binder, arg0, arg1);
}
}
internal static DynamicExpression Make(Type returnType, Type delegateType, CallSiteBinder binder, Expression arg0, Expression arg1, Expression arg2) {
if (returnType == typeof(object)) {
return new DynamicExpression3(delegateType, binder, arg0, arg1, arg2);
} else {
return new TypedDynamicExpression3(returnType, delegateType, binder, arg0, arg1, arg2);
}
}
internal static DynamicExpression Make(Type returnType, Type delegateType, CallSiteBinder binder, Expression arg0, Expression arg1, Expression arg2, Expression arg3) {
if (returnType == typeof(object)) {
return new DynamicExpression4(delegateType, binder, arg0, arg1, arg2, arg3);
} else {
return new TypedDynamicExpression4(returnType, delegateType, binder, arg0, arg1, arg2, arg3);
}
}
///
/// Gets the static type of the expression that this represents.
///
/// The that represents the static type of the expression.
public override Type Type {
get { return typeof(object); }
}
///
/// Returns the node type of this Expression. Extension nodes should return
/// ExpressionType.Extension when overriding this method.
///
/// The of the expression.
public sealed override ExpressionType NodeType {
get { return ExpressionType.Dynamic; }
}
///
/// Gets the , which determines the runtime behavior of the
/// dynamic site.
///
public CallSiteBinder Binder {
get { return _binder; }
}
///
/// Gets the type of the delegate used by the .
///
public Type DelegateType {
get { return _delegateType; }
}
///
/// Gets the arguments to the dynamic operation.
///
public ReadOnlyCollection Arguments {
get { return GetOrMakeArguments(); }
}
internal virtual ReadOnlyCollection GetOrMakeArguments() {
throw ContractUtils.Unreachable;
}
///
/// Dispatches to the specific visit method for this node type.
///
protected internal override Expression Accept(ExpressionVisitor visitor) {
return visitor.VisitDynamic(this);
}
///
/// Makes a copy of this node replacing the args with the provided values. The
/// number of the args needs to match the number of the current block.
///
/// This helper is provided to allow re-writing of nodes to not depend on the specific optimized
/// subclass of DynamicExpression which is being used.
///
internal virtual DynamicExpression Rewrite(Expression[] args) {
throw ContractUtils.Unreachable;
}
///
/// Creates a new expression that is like this one, but using the
/// supplied children. If all of the children are the same, it will
/// return this expression.
///
/// The property of the result.
/// This expression if no children changed, or an expression with the updated children.
public DynamicExpression Update(IEnumerable arguments) {
if (arguments == Arguments) {
return this;
}
return Expression.MakeDynamic(DelegateType, Binder, arguments);
}
#region IArgumentProvider Members
Expression IArgumentProvider.GetArgument(int index) {
throw ContractUtils.Unreachable;
}
int IArgumentProvider.ArgumentCount {
get { throw ContractUtils.Unreachable; }
}
#endregion
}
#region Specialized Subclasses
internal class DynamicExpressionN : DynamicExpression, IArgumentProvider {
private IList _arguments; // storage for the original IList or readonly collection. See IArgumentProvider for more info.
internal DynamicExpressionN(Type delegateType, CallSiteBinder binder, IList arguments)
: base(delegateType, binder) {
_arguments = arguments;
}
Expression IArgumentProvider.GetArgument(int index) {
return _arguments[index];
}
int IArgumentProvider.ArgumentCount {
get {
return _arguments.Count;
}
}
internal override ReadOnlyCollection GetOrMakeArguments() {
return ReturnReadOnly(ref _arguments);
}
internal override DynamicExpression Rewrite(Expression[] args) {
Debug.Assert(args.Length == ((IArgumentProvider)this).ArgumentCount);
return Expression.MakeDynamic(DelegateType, Binder, args);
}
}
internal class TypedDynamicExpressionN : DynamicExpressionN {
private readonly Type _returnType;
internal TypedDynamicExpressionN(Type returnType, Type delegateType, CallSiteBinder binder, IList arguments)
: base(delegateType, binder, arguments) {
Debug.Assert(delegateType.GetMethod("Invoke").GetReturnType() == returnType);
_returnType = returnType;
}
public sealed override Type Type {
get { return _returnType; }
}
}
internal class DynamicExpression1 : DynamicExpression, IArgumentProvider {
private object _arg0; // storage for the 1st argument or a readonly collection. See IArgumentProvider for more info.
internal DynamicExpression1(Type delegateType, CallSiteBinder binder, Expression arg0)
: base(delegateType, binder) {
_arg0 = arg0;
}
Expression IArgumentProvider.GetArgument(int index) {
switch (index) {
case 0: return ReturnObject(_arg0);
default: throw new InvalidOperationException();
}
}
int IArgumentProvider.ArgumentCount {
get {
return 1;
}
}
internal override ReadOnlyCollection GetOrMakeArguments() {
return ReturnReadOnly(this, ref _arg0);
}
internal override DynamicExpression Rewrite(Expression[] args) {
Debug.Assert(args.Length == 1);
return Expression.MakeDynamic(DelegateType, Binder, args[0]);
}
}
internal sealed class TypedDynamicExpression1 : DynamicExpression1 {
private readonly Type _retType;
internal TypedDynamicExpression1(Type retType, Type delegateType, CallSiteBinder binder, Expression arg0)
: base(delegateType, binder, arg0) {
_retType = retType;
}
public sealed override Type Type {
get { return _retType; }
}
}
internal class DynamicExpression2 : DynamicExpression, IArgumentProvider {
private object _arg0; // storage for the 1st argument or a readonly collection. See IArgumentProvider for more info.
private readonly Expression _arg1; // storage for the 2nd argument
internal DynamicExpression2(Type delegateType, CallSiteBinder binder, Expression arg0, Expression arg1)
: base(delegateType, binder) {
_arg0 = arg0;
_arg1 = arg1;
}
Expression IArgumentProvider.GetArgument(int index) {
switch (index) {
case 0: return ReturnObject(_arg0);
case 1: return _arg1;
default: throw new InvalidOperationException();
}
}
int IArgumentProvider.ArgumentCount {
get {
return 2;
}
}
internal override ReadOnlyCollection GetOrMakeArguments() {
return ReturnReadOnly(this, ref _arg0);
}
internal override DynamicExpression Rewrite(Expression[] args) {
Debug.Assert(args.Length == 2);
return Expression.MakeDynamic(DelegateType, Binder, args[0], args[1]);
}
}
internal sealed class TypedDynamicExpression2 : DynamicExpression2 {
private readonly Type _retType;
internal TypedDynamicExpression2(Type retType, Type delegateType, CallSiteBinder binder, Expression arg0, Expression arg1)
: base(delegateType, binder, arg0, arg1) {
_retType = retType;
}
public sealed override Type Type {
get { return _retType; }
}
}
internal class DynamicExpression3 : DynamicExpression, IArgumentProvider {
private object _arg0; // storage for the 1st argument or a readonly collection. See IArgumentProvider for more info.
private readonly Expression _arg1, _arg2; // storage for the 2nd & 3rd arguments
internal DynamicExpression3(Type delegateType, CallSiteBinder binder, Expression arg0, Expression arg1, Expression arg2)
: base(delegateType, binder) {
_arg0 = arg0;
_arg1 = arg1;
_arg2 = arg2;
}
Expression IArgumentProvider.GetArgument(int index) {
switch (index) {
case 0: return ReturnObject(_arg0);
case 1: return _arg1;
case 2: return _arg2;
default: throw new InvalidOperationException();
}
}
int IArgumentProvider.ArgumentCount {
get {
return 3;
}
}
internal override ReadOnlyCollection GetOrMakeArguments() {
return ReturnReadOnly(this, ref _arg0);
}
internal override DynamicExpression Rewrite(Expression[] args) {
Debug.Assert(args.Length == 3);
return Expression.MakeDynamic(DelegateType, Binder, args[0], args[1], args[2]);
}
}
internal sealed class TypedDynamicExpression3 : DynamicExpression3 {
private readonly Type _retType;
internal TypedDynamicExpression3(Type retType, Type delegateType, CallSiteBinder binder, Expression arg0, Expression arg1, Expression arg2)
: base(delegateType, binder, arg0, arg1, arg2) {
_retType = retType;
}
public sealed override Type Type {
get { return _retType; }
}
}
internal class DynamicExpression4 : DynamicExpression, IArgumentProvider {
private object _arg0; // storage for the 1st argument or a readonly collection. See IArgumentProvider for more info.
private readonly Expression _arg1, _arg2, _arg3; // storage for the 2nd - 4th arguments
internal DynamicExpression4(Type delegateType, CallSiteBinder binder, Expression arg0, Expression arg1, Expression arg2, Expression arg3)
: base(delegateType, binder) {
_arg0 = arg0;
_arg1 = arg1;
_arg2 = arg2;
_arg3 = arg3;
}
Expression IArgumentProvider.GetArgument(int index) {
switch (index) {
case 0: return ReturnObject(_arg0);
case 1: return _arg1;
case 2: return _arg2;
case 3: return _arg3;
default: throw new InvalidOperationException();
}
}
int IArgumentProvider.ArgumentCount {
get {
return 4;
}
}
internal override ReadOnlyCollection GetOrMakeArguments() {
return ReturnReadOnly(this, ref _arg0);
}
internal override DynamicExpression Rewrite(Expression[] args) {
Debug.Assert(args.Length == 4);
return Expression.MakeDynamic(DelegateType, Binder, args[0], args[1], args[2], args[3]);
}
}
internal sealed class TypedDynamicExpression4 : DynamicExpression4 {
private readonly Type _retType;
internal TypedDynamicExpression4(Type retType, Type delegateType, CallSiteBinder binder, Expression arg0, Expression arg1, Expression arg2, Expression arg3)
: base(delegateType, binder, arg0, arg1, arg2, arg3) {
_retType = retType;
}
public sealed override Type Type {
get { return _retType; }
}
}
#endregion
public partial class Expression {
///
/// Creates a that represents a dynamic operation bound by the provided .
///
/// The type of the delegate used by the .
/// The runtime binder for the dynamic operation.
/// The arguments to the dynamic operation.
///
/// A that has equal to
/// Dynamic and has the
/// DelegateType ,
/// Binder , and
/// Arguments set to the specified values.
///
public static DynamicExpression MakeDynamic(Type delegateType, CallSiteBinder binder, params Expression[] arguments) {
return MakeDynamic(delegateType, binder, (IEnumerable)arguments);
}
///
/// Creates a that represents a dynamic operation bound by the provided .
///
/// The type of the delegate used by the .
/// The runtime binder for the dynamic operation.
/// The arguments to the dynamic operation.
///
/// A that has equal to
/// Dynamic and has the
/// DelegateType ,
/// Binder , and
/// Arguments set to the specified values.
///
public static DynamicExpression MakeDynamic(Type delegateType, CallSiteBinder binder, IEnumerable arguments) {
ContractUtils.RequiresNotNull(delegateType, "delegateType");
ContractUtils.RequiresNotNull(binder, "binder");
if (!delegateType.IsSubclassOf(typeof(Delegate))) throw Error.TypeMustBeDerivedFromSystemDelegate();
var method = GetValidMethodForDynamic(delegateType);
var args = arguments.ToReadOnly();
ValidateArgumentTypes(method, ExpressionType.Dynamic, ref args);
return DynamicExpression.Make(method.GetReturnType(), delegateType, binder, args);
}
///
/// Creates a that represents a dynamic operation bound by the provided and one argument.
///
/// The type of the delegate used by the .
/// The runtime binder for the dynamic operation.
/// The argument to the dynamic operation.
///
/// A that has equal to
/// Dynamic and has the
/// DelegateType ,
/// Binder , and
/// Arguments set to the specified values.
///
public static DynamicExpression MakeDynamic(Type delegateType, CallSiteBinder binder, Expression arg0) {
ContractUtils.RequiresNotNull(delegateType, "delegatType");
ContractUtils.RequiresNotNull(binder, "binder");
if (!delegateType.IsSubclassOf(typeof(Delegate))) throw Error.TypeMustBeDerivedFromSystemDelegate();
var method = GetValidMethodForDynamic(delegateType);
var parameters = method.GetParametersCached();
ValidateArgumentCount(method, ExpressionType.Dynamic, 2, parameters);
ValidateDynamicArgument(arg0);
ValidateOneArgument(method, ExpressionType.Dynamic, arg0, parameters[1]);
return DynamicExpression.Make(method.GetReturnType(), delegateType, binder, arg0);
}
///
/// Creates a that represents a dynamic operation bound by the provided and two arguments.
///
/// The type of the delegate used by the .
/// The runtime binder for the dynamic operation.
/// The first argument to the dynamic operation.
/// The second argument to the dynamic operation.
///
/// A that has equal to
/// Dynamic and has the
/// DelegateType ,
/// Binder , and
/// Arguments set to the specified values.
///
public static DynamicExpression MakeDynamic(Type delegateType, CallSiteBinder binder, Expression arg0, Expression arg1) {
ContractUtils.RequiresNotNull(delegateType, "delegatType");
ContractUtils.RequiresNotNull(binder, "binder");
if (!delegateType.IsSubclassOf(typeof(Delegate))) throw Error.TypeMustBeDerivedFromSystemDelegate();
var method = GetValidMethodForDynamic(delegateType);
var parameters = method.GetParametersCached();
ValidateArgumentCount(method, ExpressionType.Dynamic, 3, parameters);
ValidateDynamicArgument(arg0);
ValidateOneArgument(method, ExpressionType.Dynamic, arg0, parameters[1]);
ValidateDynamicArgument(arg1);
ValidateOneArgument(method, ExpressionType.Dynamic, arg1, parameters[2]);
return DynamicExpression.Make(method.GetReturnType(), delegateType, binder, arg0, arg1);
}
///
/// Creates a that represents a dynamic operation bound by the provided and three arguments.
///
/// The type of the delegate used by the .
/// The runtime binder for the dynamic operation.
/// The first argument to the dynamic operation.
/// The second argument to the dynamic operation.
/// The third argument to the dynamic operation.
///
/// A that has equal to
/// Dynamic and has the
/// DelegateType ,
/// Binder , and
/// Arguments set to the specified values.
///
public static DynamicExpression MakeDynamic(Type delegateType, CallSiteBinder binder, Expression arg0, Expression arg1, Expression arg2) {
ContractUtils.RequiresNotNull(delegateType, "delegatType");
ContractUtils.RequiresNotNull(binder, "binder");
if (!delegateType.IsSubclassOf(typeof(Delegate))) throw Error.TypeMustBeDerivedFromSystemDelegate();
var method = GetValidMethodForDynamic(delegateType);
var parameters = method.GetParametersCached();
ValidateArgumentCount(method, ExpressionType.Dynamic, 4, parameters);
ValidateDynamicArgument(arg0);
ValidateOneArgument(method, ExpressionType.Dynamic, arg0, parameters[1]);
ValidateDynamicArgument(arg1);
ValidateOneArgument(method, ExpressionType.Dynamic, arg1, parameters[2]);
ValidateDynamicArgument(arg2);
ValidateOneArgument(method, ExpressionType.Dynamic, arg2, parameters[3]);
return DynamicExpression.Make(method.GetReturnType(), delegateType, binder, arg0, arg1, arg2);
}
///
/// Creates a that represents a dynamic operation bound by the provided and four arguments.
///
/// The type of the delegate used by the .
/// The runtime binder for the dynamic operation.
/// The first argument to the dynamic operation.
/// The second argument to the dynamic operation.
/// The third argument to the dynamic operation.
/// The fourth argument to the dynamic operation.
///
/// A that has equal to
/// Dynamic and has the
/// DelegateType ,
/// Binder , and
/// Arguments set to the specified values.
///
public static DynamicExpression MakeDynamic(Type delegateType, CallSiteBinder binder, Expression arg0, Expression arg1, Expression arg2, Expression arg3) {
ContractUtils.RequiresNotNull(delegateType, "delegatType");
ContractUtils.RequiresNotNull(binder, "binder");
if (!delegateType.IsSubclassOf(typeof(Delegate))) throw Error.TypeMustBeDerivedFromSystemDelegate();
var method = GetValidMethodForDynamic(delegateType);
var parameters = method.GetParametersCached();
ValidateArgumentCount(method, ExpressionType.Dynamic, 5, parameters);
ValidateDynamicArgument(arg0);
ValidateOneArgument(method, ExpressionType.Dynamic, arg0, parameters[1]);
ValidateDynamicArgument(arg1);
ValidateOneArgument(method, ExpressionType.Dynamic, arg1, parameters[2]);
ValidateDynamicArgument(arg2);
ValidateOneArgument(method, ExpressionType.Dynamic, arg2, parameters[3]);
ValidateDynamicArgument(arg3);
ValidateOneArgument(method, ExpressionType.Dynamic, arg3, parameters[4]);
return DynamicExpression.Make(method.GetReturnType(), delegateType, binder, arg0, arg1, arg2, arg3);
}
private static MethodInfo GetValidMethodForDynamic(Type delegateType) {
var method = delegateType.GetMethod("Invoke");
var pi = method.GetParametersCached();
if (pi.Length == 0 || pi[0].ParameterType != typeof(CallSite)) throw Error.FirstArgumentMustBeCallSite();
return method;
}
///
/// Creates a that represents a dynamic operation bound by the provided .
///
/// The runtime binder for the dynamic operation.
/// The result type of the dynamic expression.
/// The arguments to the dynamic operation.
///
/// A that has equal to
/// Dynamic and has the
/// Binder and
/// Arguments set to the specified values.
///
///
/// The DelegateType property of the
/// result will be inferred from the types of the arguments and the specified return type.
///
public static DynamicExpression Dynamic(CallSiteBinder binder, Type returnType, params Expression[] arguments) {
return Dynamic(binder, returnType, (IEnumerable)arguments);
}
///
/// Creates a that represents a dynamic operation bound by the provided .
///
/// The runtime binder for the dynamic operation.
/// The result type of the dynamic expression.
/// The first argument to the dynamic operation.
///
/// A that has equal to
/// Dynamic and has the
/// Binder and
/// Arguments set to the specified values.
///
///
/// The DelegateType property of the
/// result will be inferred from the types of the arguments and the specified return type.
///
public static DynamicExpression Dynamic(CallSiteBinder binder, Type returnType, Expression arg0) {
ContractUtils.RequiresNotNull(binder, "binder");
ValidateDynamicArgument(arg0);
DelegateHelpers.TypeInfo info = DelegateHelpers.GetNextTypeInfo(
returnType,
DelegateHelpers.GetNextTypeInfo(
arg0.Type,
DelegateHelpers.NextTypeInfo(typeof(CallSite))
)
);
Type delegateType = info.DelegateType;
if (delegateType == null) {
delegateType = info.MakeDelegateType(returnType, arg0);
}
return DynamicExpression.Make(returnType, delegateType, binder, arg0);
}
///
/// Creates a that represents a dynamic operation bound by the provided .
///
/// The runtime binder for the dynamic operation.
/// The result type of the dynamic expression.
/// The first argument to the dynamic operation.
/// The second argument to the dynamic operation.
///
/// A that has equal to
/// Dynamic and has the
/// Binder and
/// Arguments set to the specified values.
///
///
/// The DelegateType property of the
/// result will be inferred from the types of the arguments and the specified return type.
///
public static DynamicExpression Dynamic(CallSiteBinder binder, Type returnType, Expression arg0, Expression arg1) {
ContractUtils.RequiresNotNull(binder, "binder");
ValidateDynamicArgument(arg0);
ValidateDynamicArgument(arg1);
DelegateHelpers.TypeInfo info = DelegateHelpers.GetNextTypeInfo(
returnType,
DelegateHelpers.GetNextTypeInfo(
arg1.Type,
DelegateHelpers.GetNextTypeInfo(
arg0.Type,
DelegateHelpers.NextTypeInfo(typeof(CallSite))
)
)
);
Type delegateType = info.DelegateType;
if (delegateType == null) {
delegateType = info.MakeDelegateType(returnType, arg0, arg1);
}
return DynamicExpression.Make(returnType, delegateType, binder, arg0, arg1);
}
///
/// Creates a that represents a dynamic operation bound by the provided .
///
/// The runtime binder for the dynamic operation.
/// The result type of the dynamic expression.
/// The first argument to the dynamic operation.
/// The second argument to the dynamic operation.
/// The third argument to the dynamic operation.
///
/// A that has equal to
/// Dynamic and has the
/// Binder and
/// Arguments set to the specified values.
///
///
/// The DelegateType property of the
/// result will be inferred from the types of the arguments and the specified return type.
///
public static DynamicExpression Dynamic(CallSiteBinder binder, Type returnType, Expression arg0, Expression arg1, Expression arg2) {
ContractUtils.RequiresNotNull(binder, "binder");
ValidateDynamicArgument(arg0);
ValidateDynamicArgument(arg1);
ValidateDynamicArgument(arg2);
DelegateHelpers.TypeInfo info = DelegateHelpers.GetNextTypeInfo(
returnType,
DelegateHelpers.GetNextTypeInfo(
arg2.Type,
DelegateHelpers.GetNextTypeInfo(
arg1.Type,
DelegateHelpers.GetNextTypeInfo(
arg0.Type,
DelegateHelpers.NextTypeInfo(typeof(CallSite))
)
)
)
);
Type delegateType = info.DelegateType;
if (delegateType == null) {
delegateType = info.MakeDelegateType(returnType, arg0, arg1, arg2);
}
return DynamicExpression.Make(returnType, delegateType, binder, arg0, arg1, arg2);
}
///
/// Creates a that represents a dynamic operation bound by the provided .
///
/// The runtime binder for the dynamic operation.
/// The result type of the dynamic expression.
/// The first argument to the dynamic operation.
/// The second argument to the dynamic operation.
/// The third argument to the dynamic operation.
/// The fourth argument to the dynamic operation.
///
/// A that has equal to
/// Dynamic and has the
/// Binder and
/// Arguments set to the specified values.
///
///
/// The DelegateType property of the
/// result will be inferred from the types of the arguments and the specified return type.
///
public static DynamicExpression Dynamic(CallSiteBinder binder, Type returnType, Expression arg0, Expression arg1, Expression arg2, Expression arg3) {
ContractUtils.RequiresNotNull(binder, "binder");
ValidateDynamicArgument(arg0);
ValidateDynamicArgument(arg1);
ValidateDynamicArgument(arg2);
ValidateDynamicArgument(arg3);
DelegateHelpers.TypeInfo info = DelegateHelpers.GetNextTypeInfo(
returnType,
DelegateHelpers.GetNextTypeInfo(
arg3.Type,
DelegateHelpers.GetNextTypeInfo(
arg2.Type,
DelegateHelpers.GetNextTypeInfo(
arg1.Type,
DelegateHelpers.GetNextTypeInfo(
arg0.Type,
DelegateHelpers.NextTypeInfo(typeof(CallSite))
)
)
)
)
);
Type delegateType = info.DelegateType;
if (delegateType == null) {
delegateType = info.MakeDelegateType(returnType, arg0, arg1, arg2, arg3);
}
return DynamicExpression.Make(returnType, delegateType, binder, arg0, arg1, arg2, arg3);
}
///
/// Creates a that represents a dynamic operation bound by the provided .
///
/// The runtime binder for the dynamic operation.
/// The result type of the dynamic expression.
/// The arguments to the dynamic operation.
///
/// A that has equal to
/// Dynamic and has the
/// Binder and
/// Arguments set to the specified values.
///
///
/// The DelegateType property of the
/// result will be inferred from the types of the arguments and the specified return type.
///
public static DynamicExpression Dynamic(CallSiteBinder binder, Type returnType, IEnumerable arguments) {
ContractUtils.RequiresNotNull(arguments, "arguments");
ContractUtils.RequiresNotNull(returnType, "returnType");
var args = arguments.ToReadOnly();
ContractUtils.RequiresNotEmpty(args, "args");
return MakeDynamic(binder, returnType, args);
}
private static DynamicExpression MakeDynamic(CallSiteBinder binder, Type returnType, ReadOnlyCollection args) {
ContractUtils.RequiresNotNull(binder, "binder");
for (int i = 0; i < args.Count; i++) {
Expression arg = args[i];
ValidateDynamicArgument(arg);
}
Type delegateType = DelegateHelpers.MakeCallSiteDelegate(args, returnType);
// Since we made a delegate with argument types that exactly match,
// we can skip delegate and argument validation
switch (args.Count) {
case 1: return DynamicExpression.Make(returnType, delegateType, binder, args[0]);
case 2: return DynamicExpression.Make(returnType, delegateType, binder, args[0], args[1]);
case 3: return DynamicExpression.Make(returnType, delegateType, binder, args[0], args[1], args[2]);
case 4: return DynamicExpression.Make(returnType, delegateType, binder, args[0], args[1], args[2], args[3]);
default: return DynamicExpression.Make(returnType, delegateType, binder, args);
}
}
private static void ValidateDynamicArgument(Expression arg) {
RequiresCanRead(arg, "arguments");
var type = arg.Type;
ContractUtils.RequiresNotNull(type, "type");
TypeUtils.ValidateType(type);
if (type == typeof(void)) throw Error.ArgumentTypeCannotBeVoid();
}
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- DependentList.cs
- EntityDataSourceColumn.cs
- PageAsyncTaskManager.cs
- ClaimComparer.cs
- HyperLinkField.cs
- WebConfigurationHost.cs
- CheckedPointers.cs
- Rss20FeedFormatter.cs
- ListView.cs
- FileDialogCustomPlace.cs
- ComboBox.cs
- _ChunkParse.cs
- SqlBulkCopy.cs
- AnimationStorage.cs
- BuildProviderCollection.cs
- LogicalExpr.cs
- GeneratedView.cs
- SqlClientWrapperSmiStreamChars.cs
- StorageAssociationSetMapping.cs
- SupportsPreviewControlAttribute.cs
- CryptoStream.cs
- WmfPlaceableFileHeader.cs
- TypeSystem.cs
- SessionStateUtil.cs
- FormsIdentity.cs
- DocumentViewerConstants.cs
- ExpressionConverter.cs
- OleDbMetaDataFactory.cs
- WebServiceClientProxyGenerator.cs
- Calendar.cs
- Calendar.cs
- OverflowException.cs
- GridViewCancelEditEventArgs.cs
- SerTrace.cs
- TextSelection.cs
- SafeSystemMetrics.cs
- ZipPackage.cs
- XmlSignificantWhitespace.cs
- TransformerConfigurationWizardBase.cs
- DEREncoding.cs
- BindingOperations.cs
- ToolStripManager.cs
- PointIndependentAnimationStorage.cs
- IListConverters.cs
- StoryFragments.cs
- WebPartManagerInternals.cs
- ForwardPositionQuery.cs
- EventHandlerList.cs
- WindowsScroll.cs
- ExpressionTable.cs
- precedingquery.cs
- ExpressionBuilder.cs
- DesignTableCollection.cs
- SoapObjectReader.cs
- RegexCaptureCollection.cs
- PrinterSettings.cs
- MenuBase.cs
- SkewTransform.cs
- KnownTypesProvider.cs
- storepermission.cs
- DrawingAttributeSerializer.cs
- IpcClientManager.cs
- HighContrastHelper.cs
- SerializerDescriptor.cs
- ComUdtElementCollection.cs
- COM2Enum.cs
- ActivationServices.cs
- InheritanceUI.cs
- BulletDecorator.cs
- EntityDataSourceQueryBuilder.cs
- Span.cs
- PerCallInstanceContextProvider.cs
- ScrollChangedEventArgs.cs
- CdpEqualityComparer.cs
- SimpleParser.cs
- ProxyWebPart.cs
- ThreadExceptionEvent.cs
- DesignerHelpers.cs
- ValidatingPropertiesEventArgs.cs
- RectAnimationBase.cs
- MediaEntryAttribute.cs
- CodeGenerator.cs
- CultureMapper.cs
- WmlLabelAdapter.cs
- panel.cs
- AssociationTypeEmitter.cs
- XmlNamedNodeMap.cs
- SharedPerformanceCounter.cs
- HtmlTernaryTree.cs
- CanonicalFontFamilyReference.cs
- Accessible.cs
- VoiceChangeEventArgs.cs
- X509Chain.cs
- FrameAutomationPeer.cs
- MenuEventArgs.cs
- QilValidationVisitor.cs
- GACIdentityPermission.cs
- wgx_commands.cs
- SQLRoleProvider.cs
- HMACSHA1.cs