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
- Window.cs
- CalloutQueueItem.cs
- LinqDataSourceHelper.cs
- OutputCacheSettings.cs
- Debugger.cs
- ToolStripTemplateNode.cs
- StorageModelBuildProvider.cs
- DrawingContextDrawingContextWalker.cs
- DragDrop.cs
- Error.cs
- SharedPersonalizationStateInfo.cs
- ServiceRouteHandler.cs
- ClientSponsor.cs
- SynchronizedInputPattern.cs
- XpsTokenContext.cs
- StickyNoteAnnotations.cs
- HttpWriter.cs
- InstallerTypeAttribute.cs
- IPeerNeighbor.cs
- WebRequestModulesSection.cs
- BeginEvent.cs
- ManagementBaseObject.cs
- SingleKeyFrameCollection.cs
- HyperLinkField.cs
- TitleStyle.cs
- Span.cs
- IgnoreFileBuildProvider.cs
- ServiceHttpModule.cs
- Vector3D.cs
- RenderContext.cs
- HuffModule.cs
- CollectionsUtil.cs
- BackgroundWorker.cs
- QilInvokeEarlyBound.cs
- VarRefManager.cs
- SByteStorage.cs
- HttpRawResponse.cs
- CodeCastExpression.cs
- StoreAnnotationsMap.cs
- StyleSelector.cs
- TableLayoutPanel.cs
- _ConnectionGroup.cs
- EntityClientCacheEntry.cs
- ObjectIDGenerator.cs
- ImpersonateTokenRef.cs
- ConfigXmlText.cs
- XmlSchemaElement.cs
- ShutDownListener.cs
- BitStack.cs
- Predicate.cs
- SymmetricAlgorithm.cs
- DictionaryEntry.cs
- NoneExcludedImageIndexConverter.cs
- ContractListAdapter.cs
- FigureHelper.cs
- DataGridRow.cs
- ObfuscationAttribute.cs
- ContextStack.cs
- DataKey.cs
- HMACSHA1.cs
- TextElementEnumerator.cs
- SqlInternalConnectionSmi.cs
- CharAnimationUsingKeyFrames.cs
- MobileControlBuilder.cs
- cookieexception.cs
- Encoding.cs
- FieldDescriptor.cs
- AnimationTimeline.cs
- XmlNamespaceMapping.cs
- SchemaManager.cs
- DictionaryItemsCollection.cs
- IImplicitResourceProvider.cs
- XPathMultyIterator.cs
- SqlDuplicator.cs
- FontFamilyValueSerializer.cs
- LoginView.cs
- SamlDelegatingWriter.cs
- OracleSqlParser.cs
- ContextMenuService.cs
- NotificationContext.cs
- LogEntrySerializer.cs
- ErrorEventArgs.cs
- AsyncOperationContext.cs
- EventLogPermission.cs
- TemplateAction.cs
- DataBindingValueUIHandler.cs
- WCFModelStrings.Designer.cs
- MetadataArtifactLoaderXmlReaderWrapper.cs
- TempFiles.cs
- TextBounds.cs
- ApplicationActivator.cs
- ParameterCollection.cs
- DelegatingConfigHost.cs
- DataPagerCommandEventArgs.cs
- NodeFunctions.cs
- ISFTagAndGuidCache.cs
- CrossContextChannel.cs
- DrawListViewItemEventArgs.cs
- DataServiceConfiguration.cs
- CallSiteOps.cs