Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / Core / Microsoft / Scripting / Ast / LambdaExpression.cs / 1305376 / LambdaExpression.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.Reflection.Emit; using System.Threading; using System.Runtime.CompilerServices; #if SILVERLIGHT using System.Core; #endif namespace System.Linq.Expressions { ////// Creates a ///node. /// This captures a block of code that is similar to a .NET method body. /// /// Lambda expressions take input through parameters and are expected to be fully bound. /// #if !SILVERLIGHT [DebuggerTypeProxy(typeof(Expression.LambdaExpressionProxy))] #endif public abstract class LambdaExpression : Expression { private readonly string _name; private readonly Expression _body; private readonly ReadOnlyCollection_parameters; private readonly Type _delegateType; private readonly bool _tailCall; internal LambdaExpression( Type delegateType, string name, Expression body, bool tailCall, ReadOnlyCollection parameters ) { Debug.Assert(delegateType != null); _name = name; _body = body; _parameters = parameters; _delegateType = delegateType; _tailCall = tailCall; } /// /// Gets the static type of the expression that this ///represents. (Inherited from .) /// The public sealed override Type Type { get { return _delegateType; } } ///that represents the static type of the expression. /// Returns the node type of this ///. (Inherited from .) /// The public sealed override ExpressionType NodeType { get { return ExpressionType.Lambda; } } ///that represents this expression. /// Gets the parameters of the lambda expression. /// public ReadOnlyCollectionParameters { get { return _parameters; } } /// /// Gets the name of the lambda expression. /// ///Used for debugging purposes. public string Name { get { return _name; } } ////// Gets the body of the lambda expression. /// public Expression Body { get { return _body; } } ////// Gets the return type of the lambda expression. /// public Type ReturnType { get { return Type.GetMethod("Invoke").ReturnType; } } ////// Gets the value that indicates if the lambda expression will be compiled with /// tail call optimization. /// public bool TailCall { get { return _tailCall; } } ////// Produces a delegate that represents the lambda expression. /// ///A delegate containing the compiled version of the lambda. public Delegate Compile() { return LambdaCompiler.Compile(this, null); } ////// Produces a delegate that represents the lambda expression. /// /// Debugging information generator used by the compiler to mark sequence points and annotate local variables. ///A delegate containing the compiled version of the lambda. public Delegate Compile(DebugInfoGenerator debugInfoGenerator) { ContractUtils.RequiresNotNull(debugInfoGenerator, "debugInfoGenerator"); return LambdaCompiler.Compile(this, debugInfoGenerator); } ////// Compiles the lambda into a method definition. /// /// Awhich will be used to hold the lambda's IL. public void CompileToMethod(MethodBuilder method) { CompileToMethodInternal(method, null); } /// /// Compiles the lambda into a method definition and custom debug information. /// /// Awhich will be used to hold the lambda's IL. /// Debugging information generator used by the compiler to mark sequence points and annotate local variables. public void CompileToMethod(MethodBuilder method, DebugInfoGenerator debugInfoGenerator) { ContractUtils.RequiresNotNull(debugInfoGenerator, "debugInfoGenerator"); CompileToMethodInternal(method, debugInfoGenerator); } private void CompileToMethodInternal(MethodBuilder method, DebugInfoGenerator debugInfoGenerator) { ContractUtils.RequiresNotNull(method, "method"); ContractUtils.Requires(method.IsStatic, "method"); var type = method.DeclaringType as TypeBuilder; if (type == null) throw Error.MethodBuilderDoesNotHaveTypeBuilder(); LambdaCompiler.Compile(this, method, debugInfoGenerator); } internal abstract LambdaExpression Accept(StackSpiller spiller); } /// /// Defines a ///node. /// This captures a block of code that is similar to a .NET method body. /// The type of the delegate. ////// Lambda expressions take input through parameters and are expected to be fully bound. /// public sealed class Expression: LambdaExpression { internal Expression(Expression body, string name, bool tailCall, ReadOnlyCollection parameters) : base(typeof(TDelegate), name, body, tailCall, parameters) { } /// /// Produces a delegate that represents the lambda expression. /// ///A delegate containing the compiled version of the lambda. public new TDelegate Compile() { return (TDelegate)(object)LambdaCompiler.Compile(this, null); } ////// Produces a delegate that represents the lambda expression. /// /// Debugging information generator used by the compiler to mark sequence points and annotate local variables. ///A delegate containing the compiled version of the lambda. public new TDelegate Compile(DebugInfoGenerator debugInfoGenerator) { ContractUtils.RequiresNotNull(debugInfoGenerator, "debugInfoGenerator"); return (TDelegate)(object)LambdaCompiler.Compile(this, debugInfoGenerator); } ////// 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. /// /// TheBody property of the result. /// TheParameters property of the result. ///This expression if no children changed, or an expression with the updated children. public ExpressionUpdate(Expression body, IEnumerable parameters) { if (body == Body && parameters == Parameters) { return this; } return Expression.Lambda (body, Name, TailCall, parameters); } /// /// Dispatches to the specific visit method for this node type. /// protected internal override Expression Accept(ExpressionVisitor visitor) { return visitor.VisitLambda(this); } internal override LambdaExpression Accept(StackSpiller spiller) { return spiller.Rewrite(this); } internal static LambdaExpression Create(Expression body, string name, bool tailCall, ReadOnlyCollectionparameters) { return new Expression (body, name, tailCall, parameters); } } public partial class Expression { /// /// Creates an Expression{T} given the delegate type. Caches the /// factory method to speed up repeated creations for the same T. /// internal static LambdaExpression CreateLambda(Type delegateType, Expression body, string name, bool tailCall, ReadOnlyCollectionparameters) { // Get or create a delegate to the public Expression.Lambda // method and call that will be used for creating instances of this // delegate type LambdaFactory fastPath; if (_LambdaFactories == null) { // NOTE: this must be Interlocked ----igment since we use _LambdaFactories for locking. Interlocked.CompareExchange(ref _LambdaFactories, new CacheDict (50), null); } MethodInfo create = null; lock (_LambdaFactories) { if (!_LambdaFactories.TryGetValue(delegateType, out fastPath)) { create = typeof(Expression<>).MakeGenericType(delegateType).GetMethod("Create", BindingFlags.Static | BindingFlags.NonPublic); if (TypeUtils.CanCache(delegateType)) { _LambdaFactories[delegateType] = fastPath = (LambdaFactory)Delegate.CreateDelegate(typeof(LambdaFactory), create); } } } if (fastPath != null) { return fastPath(body, name, tailCall, parameters); } Debug.Assert(create != null); return (LambdaExpression)create.Invoke(null, new object[] { body, name, tailCall, parameters }); } /// /// Creates an ///where the delegate type is known at compile time. /// The delegate type. /// Anto set the property equal to. /// An array that contains objects to use to populate the collection. /// An public static Expressionthat has the property equal to and the and properties set to the specified values. Lambda (Expression body, params ParameterExpression[] parameters) { return Lambda (body, false, (IEnumerable )parameters); } /// /// Creates an ///where the delegate type is known at compile time. /// The delegate type. /// Anto set the property equal to. /// A that indicates if tail call optimization will be applied when compiling the created expression. /// An array that contains objects to use to populate the collection. /// An public static Expressionthat has the property equal to and the and properties set to the specified values. Lambda (Expression body, bool tailCall, params ParameterExpression[] parameters) { return Lambda (body, tailCall, (IEnumerable )parameters); } /// /// Creates an ///where the delegate type is known at compile time. /// The delegate type. /// Anto set the property equal to. /// An that contains objects to use to populate the collection. /// An public static Expressionthat has the property equal to and the and properties set to the specified values. Lambda (Expression body, IEnumerable parameters) { return Lambda (body, null, false, parameters); } /// /// Creates an ///where the delegate type is known at compile time. /// The delegate type. /// Anto set the property equal to. /// A that indicates if tail call optimization will be applied when compiling the created expression. /// An that contains objects to use to populate the collection. /// An public static Expressionthat has the property equal to and the and properties set to the specified values. Lambda (Expression body, bool tailCall, IEnumerable parameters) { return Lambda (body, null, tailCall, parameters); } /// /// Creates an ///where the delegate type is known at compile time. /// The delegate type. /// Anto set the property equal to. /// An that contains objects to use to populate the collection. /// The name of the lambda. Used for generating debugging info. /// An public static Expressionthat has the property equal to and the and properties set to the specified values. Lambda (Expression body, String name, IEnumerable parameters) { return Lambda (body, name, false, parameters); } /// /// Creates an ///where the delegate type is known at compile time. /// The delegate type. /// Anto set the property equal to. /// The name of the lambda. Used for generating debugging info. /// An that contains objects to use to populate the collection. /// A that indicates if tail call optimization will be applied when compiling the created expression. /// An public static Expressionthat has the property equal to and the and properties set to the specified values. Lambda (Expression body, String name, bool tailCall, IEnumerable parameters) { var parameterList = parameters.ToReadOnly(); ValidateLambdaArgs(typeof(TDelegate), ref body, parameterList); return new Expression (body, name, tailCall, parameterList); } /// /// Creates a LambdaExpression by first constructing a delegate type. /// /// Anto set the property equal to. /// An array that contains objects to use to populate the collection. /// A public static LambdaExpression Lambda(Expression body, params ParameterExpression[] parameters) { return Lambda(body, false, (IEnumerablethat has the property equal to Lambda and the and properties set to the specified values. )parameters); } /// /// Creates a LambdaExpression by first constructing a delegate type. /// /// Anto set the property equal to. /// A that indicates if tail call optimization will be applied when compiling the created expression. /// An array that contains objects to use to populate the collection. /// A public static LambdaExpression Lambda(Expression body, bool tailCall, params ParameterExpression[] parameters) { return Lambda(body, tailCall, (IEnumerablethat has the property equal to Lambda and the and properties set to the specified values. )parameters); } /// /// Creates a LambdaExpression by first constructing a delegate type. /// /// Anto set the property equal to. /// An that contains objects to use to populate the collection. /// A public static LambdaExpression Lambda(Expression body, IEnumerablethat has the property equal to Lambda and the and properties set to the specified values. parameters) { return Lambda(body, null, false, parameters); } /// /// Creates a LambdaExpression by first constructing a delegate type. /// /// Anto set the property equal to. /// A that indicates if tail call optimization will be applied when compiling the created expression. /// An that contains objects to use to populate the collection. /// A public static LambdaExpression Lambda(Expression body, bool tailCall, IEnumerablethat has the property equal to Lambda and the and properties set to the specified values. parameters) { return Lambda(body, null, tailCall, parameters); } /// /// Creates a LambdaExpression by first constructing a delegate type. /// /// Anto set the property equal to. /// An array that contains objects to use to populate the collection. /// A representing the delegate signature for the lambda. /// A public static LambdaExpression Lambda(Type delegateType, Expression body, params ParameterExpression[] parameters) { return Lambda(delegateType, body, null, false, parameters); } ///that has the property equal to Lambda and the and properties set to the specified values. /// Creates a LambdaExpression by first constructing a delegate type. /// /// Anto set the property equal to. /// A that indicates if tail call optimization will be applied when compiling the created expression. /// An array that contains objects to use to populate the collection. /// A representing the delegate signature for the lambda. /// A public static LambdaExpression Lambda(Type delegateType, Expression body, bool tailCall, params ParameterExpression[] parameters) { return Lambda(delegateType, body, null, tailCall, parameters); } ///that has the property equal to Lambda and the and properties set to the specified values. /// Creates a LambdaExpression by first constructing a delegate type. /// /// Anto set the property equal to. /// An that contains objects to use to populate the collection. /// A representing the delegate signature for the lambda. /// A public static LambdaExpression Lambda(Type delegateType, Expression body, IEnumerablethat has the property equal to Lambda and the and properties set to the specified values. parameters) { return Lambda(delegateType, body, null, false, parameters); } /// /// Creates a LambdaExpression by first constructing a delegate type. /// /// Anto set the property equal to. /// A that indicates if tail call optimization will be applied when compiling the created expression. /// An that contains objects to use to populate the collection. /// A representing the delegate signature for the lambda. /// A public static LambdaExpression Lambda(Type delegateType, Expression body, bool tailCall, IEnumerablethat has the property equal to Lambda and the and properties set to the specified values. parameters) { return Lambda(delegateType, body, null, tailCall, parameters); } /// /// Creates a LambdaExpression by first constructing a delegate type. /// /// Anto set the property equal to. /// An that contains objects to use to populate the collection. /// The name for the lambda. Used for emitting debug information. /// A public static LambdaExpression Lambda(Expression body, string name, IEnumerablethat has the property equal to Lambda and the and properties set to the specified values. parameters) { return Lambda(body, name, false, parameters); } /// /// Creates a LambdaExpression by first constructing a delegate type. /// /// Anto set the property equal to. /// The name for the lambda. Used for emitting debug information. /// A that indicates if tail call optimization will be applied when compiling the created expression. /// An that contains objects to use to populate the collection. /// A public static LambdaExpression Lambda(Expression body, string name, bool tailCall, IEnumerablethat has the property equal to Lambda and the and properties set to the specified values. parameters) { ContractUtils.RequiresNotNull(body, "body"); var parameterList = parameters.ToReadOnly(); int paramCount = parameterList.Count; Type[] typeArgs = new Type[paramCount + 1]; if (paramCount > 0) { var set = new Set (parameterList.Count); for (int i = 0; i < paramCount; i++) { var param = parameterList[i]; ContractUtils.RequiresNotNull(param, "parameter"); typeArgs[i] = param.IsByRef ? param.Type.MakeByRefType() : param.Type; if (set.Contains(param)) { throw Error.DuplicateVariable(param); } set.Add(param); } } typeArgs[paramCount] = body.Type; Type delegateType = DelegateHelpers.MakeDelegateType(typeArgs); return CreateLambda(delegateType, body, name, tailCall, parameterList); } /// /// Creates a LambdaExpression by first constructing a delegate type. /// /// Anto set the property equal to. /// An that contains objects to use to populate the collection. /// The name for the lambda. Used for emitting debug information. /// A representing the delegate signature for the lambda. /// A public static LambdaExpression Lambda(Type delegateType, Expression body, string name, IEnumerablethat has the property equal to Lambda and the and properties set to the specified values. parameters) { var paramList = parameters.ToReadOnly(); ValidateLambdaArgs(delegateType, ref body, paramList); return CreateLambda(delegateType, body, name, false, paramList); } /// /// Creates a LambdaExpression by first constructing a delegate type. /// /// Arepresenting the delegate signature for the lambda. /// An to set the property equal to. /// The name for the lambda. Used for emitting debug information. /// A that indicates if tail call optimization will be applied when compiling the created expression. /// An that contains objects to use to populate the collection. /// A public static LambdaExpression Lambda(Type delegateType, Expression body, string name, bool tailCall, IEnumerablethat has the property equal to Lambda and the and properties set to the specified values. parameters) { var paramList = parameters.ToReadOnly(); ValidateLambdaArgs(delegateType, ref body, paramList); return CreateLambda(delegateType, body, name, tailCall, paramList); } private static void ValidateLambdaArgs(Type delegateType, ref Expression body, ReadOnlyCollection parameters) { ContractUtils.RequiresNotNull(delegateType, "delegateType"); RequiresCanRead(body, "body"); if (!typeof(Delegate).IsAssignableFrom(delegateType) || delegateType == typeof(Delegate)) { throw Error.LambdaTypeMustBeDerivedFromSystemDelegate(); } MethodInfo mi; lock (_LambdaDelegateCache) { if (!_LambdaDelegateCache.TryGetValue(delegateType, out mi)) { mi = delegateType.GetMethod("Invoke"); if (TypeUtils.CanCache(delegateType)) { _LambdaDelegateCache[delegateType] = mi; } } } ParameterInfo[] pis = mi.GetParametersCached(); if (pis.Length > 0) { if (pis.Length != parameters.Count) { throw Error.IncorrectNumberOfLambdaDeclarationParameters(); } var set = new Set (pis.Length); for (int i = 0, n = pis.Length; i < n; i++) { ParameterExpression pex = parameters[i]; ParameterInfo pi = pis[i]; RequiresCanRead(pex, "parameters"); Type pType = pi.ParameterType; if (pex.IsByRef) { if (!pType.IsByRef) { //We cannot pass a parameter of T& to a delegate that takes T or any non-ByRef type. throw Error.ParameterExpressionNotValidAsDelegate(pex.Type.MakeByRefType(), pType); } pType = pType.GetElementType(); } if (!TypeUtils.AreReferenceAssignable(pex.Type, pType)) { throw Error.ParameterExpressionNotValidAsDelegate(pex.Type, pType); } if (set.Contains(pex)) { throw Error.DuplicateVariable(pex); } set.Add(pex); } } else if (parameters.Count > 0) { throw Error.IncorrectNumberOfLambdaDeclarationParameters(); } if (mi.ReturnType != typeof(void) && !TypeUtils.AreReferenceAssignable(mi.ReturnType, body.Type)) { if (TypeUtils.IsSameOrSubclass(typeof(LambdaExpression), mi.ReturnType) && mi.ReturnType.IsAssignableFrom(body.GetType())) { body = Expression.Quote(body); } else { throw Error.ExpressionTypeDoesNotMatchReturn(body.Type, mi.ReturnType); } } } private static bool ValidateTryGetFuncActionArgs(Type[] typeArgs) { if (typeArgs == null) { throw new ArgumentNullException("typeArgs"); } for (int i = 0, n = typeArgs.Length; i < n; i++) { var a = typeArgs[i]; if (a == null) { throw new ArgumentNullException("typeArgs"); } if (a.IsByRef) { return false; } } return true; } /// /// Creates a /// An array of Type objects that specify the type arguments for the System.Func delegate type. ///object that represents a generic System.Func delegate type that has specific type arguments. /// The last type argument specifies the return type of the created delegate. /// The type of a System.Func delegate that has the specified type arguments. public static Type GetFuncType(params Type[] typeArgs) { if (!ValidateTryGetFuncActionArgs(typeArgs)) throw Error.TypeMustNotBeByRef(); Type result = DelegateHelpers.GetFuncType(typeArgs); if (result == null) { throw Error.IncorrectNumberOfTypeArgsForFunc(); } return result; } ////// Creates a /// An array of Type objects that specify the type arguments for the System.Func delegate type. /// When this method returns, contains the generic System.Func delegate type that has specific type arguments. Contains null if there is no generic System.Func delegate that matches theobject that represents a generic System.Func delegate type that has specific type arguments. /// The last type argument specifies the return type of the created delegate. /// .This parameter is passed uninitialized. /// true if generic System.Func delegate type was created for specific public static bool TryGetFuncType(Type[] typeArgs, out Type funcType) { if (ValidateTryGetFuncActionArgs(typeArgs)) { return (funcType = DelegateHelpers.GetFuncType(typeArgs)) != null; } funcType = null; return false; } ///; false otherwise. /// Creates a /// An array of Type objects that specify the type arguments for the System.Action delegate type. ///object that represents a generic System.Action delegate type that has specific type arguments. /// The type of a System.Action delegate that has the specified type arguments. public static Type GetActionType(params Type[] typeArgs) { if (!ValidateTryGetFuncActionArgs(typeArgs)) throw Error.TypeMustNotBeByRef(); Type result = DelegateHelpers.GetActionType(typeArgs); if (result == null) { throw Error.IncorrectNumberOfTypeArgsForAction(); } return result; } ////// Creates a /// An array of Type objects that specify the type arguments for the System.Action delegate type. /// When this method returns, contains the generic System.Action delegate type that has specific type arguments. Contains null if there is no generic System.Action delegate that matches theobject that represents a generic System.Action delegate type that has specific type arguments. /// .This parameter is passed uninitialized. /// true if generic System.Action delegate type was created for specific public static bool TryGetActionType(Type[] typeArgs, out Type actionType) { if (ValidateTryGetFuncActionArgs(typeArgs)) { return (actionType = DelegateHelpers.GetActionType(typeArgs)) != null; } actionType = null; return false; } ///; false otherwise. /// Gets a /// The type arguments of the delegate. ///object that represents a generic System.Func or System.Action delegate type that has specific type arguments. /// The last type argument determines the return type of the delegate. If no Func or Action is large enough, it will generate a custom /// delegate type. /// The delegate type. ////// As with Func, the last argument is the return type. It can be set /// to System.Void to produce an Action. public static Type GetDelegateType(params Type[] typeArgs) { ContractUtils.RequiresNotEmpty(typeArgs, "typeArgs"); ContractUtils.RequiresNotNullItems(typeArgs, "typeArgs"); return DelegateHelpers.MakeDelegateType(typeArgs); } } } // 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.Reflection.Emit; using System.Threading; using System.Runtime.CompilerServices; #if SILVERLIGHT using System.Core; #endif namespace System.Linq.Expressions { ////// Creates a ///node. /// This captures a block of code that is similar to a .NET method body. /// /// Lambda expressions take input through parameters and are expected to be fully bound. /// #if !SILVERLIGHT [DebuggerTypeProxy(typeof(Expression.LambdaExpressionProxy))] #endif public abstract class LambdaExpression : Expression { private readonly string _name; private readonly Expression _body; private readonly ReadOnlyCollection_parameters; private readonly Type _delegateType; private readonly bool _tailCall; internal LambdaExpression( Type delegateType, string name, Expression body, bool tailCall, ReadOnlyCollection parameters ) { Debug.Assert(delegateType != null); _name = name; _body = body; _parameters = parameters; _delegateType = delegateType; _tailCall = tailCall; } /// /// Gets the static type of the expression that this ///represents. (Inherited from .) /// The public sealed override Type Type { get { return _delegateType; } } ///that represents the static type of the expression. /// Returns the node type of this ///. (Inherited from .) /// The public sealed override ExpressionType NodeType { get { return ExpressionType.Lambda; } } ///that represents this expression. /// Gets the parameters of the lambda expression. /// public ReadOnlyCollectionParameters { get { return _parameters; } } /// /// Gets the name of the lambda expression. /// ///Used for debugging purposes. public string Name { get { return _name; } } ////// Gets the body of the lambda expression. /// public Expression Body { get { return _body; } } ////// Gets the return type of the lambda expression. /// public Type ReturnType { get { return Type.GetMethod("Invoke").ReturnType; } } ////// Gets the value that indicates if the lambda expression will be compiled with /// tail call optimization. /// public bool TailCall { get { return _tailCall; } } ////// Produces a delegate that represents the lambda expression. /// ///A delegate containing the compiled version of the lambda. public Delegate Compile() { return LambdaCompiler.Compile(this, null); } ////// Produces a delegate that represents the lambda expression. /// /// Debugging information generator used by the compiler to mark sequence points and annotate local variables. ///A delegate containing the compiled version of the lambda. public Delegate Compile(DebugInfoGenerator debugInfoGenerator) { ContractUtils.RequiresNotNull(debugInfoGenerator, "debugInfoGenerator"); return LambdaCompiler.Compile(this, debugInfoGenerator); } ////// Compiles the lambda into a method definition. /// /// Awhich will be used to hold the lambda's IL. public void CompileToMethod(MethodBuilder method) { CompileToMethodInternal(method, null); } /// /// Compiles the lambda into a method definition and custom debug information. /// /// Awhich will be used to hold the lambda's IL. /// Debugging information generator used by the compiler to mark sequence points and annotate local variables. public void CompileToMethod(MethodBuilder method, DebugInfoGenerator debugInfoGenerator) { ContractUtils.RequiresNotNull(debugInfoGenerator, "debugInfoGenerator"); CompileToMethodInternal(method, debugInfoGenerator); } private void CompileToMethodInternal(MethodBuilder method, DebugInfoGenerator debugInfoGenerator) { ContractUtils.RequiresNotNull(method, "method"); ContractUtils.Requires(method.IsStatic, "method"); var type = method.DeclaringType as TypeBuilder; if (type == null) throw Error.MethodBuilderDoesNotHaveTypeBuilder(); LambdaCompiler.Compile(this, method, debugInfoGenerator); } internal abstract LambdaExpression Accept(StackSpiller spiller); } /// /// Defines a ///node. /// This captures a block of code that is similar to a .NET method body. /// The type of the delegate. ////// Lambda expressions take input through parameters and are expected to be fully bound. /// public sealed class Expression: LambdaExpression { internal Expression(Expression body, string name, bool tailCall, ReadOnlyCollection parameters) : base(typeof(TDelegate), name, body, tailCall, parameters) { } /// /// Produces a delegate that represents the lambda expression. /// ///A delegate containing the compiled version of the lambda. public new TDelegate Compile() { return (TDelegate)(object)LambdaCompiler.Compile(this, null); } ////// Produces a delegate that represents the lambda expression. /// /// Debugging information generator used by the compiler to mark sequence points and annotate local variables. ///A delegate containing the compiled version of the lambda. public new TDelegate Compile(DebugInfoGenerator debugInfoGenerator) { ContractUtils.RequiresNotNull(debugInfoGenerator, "debugInfoGenerator"); return (TDelegate)(object)LambdaCompiler.Compile(this, debugInfoGenerator); } ////// 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. /// /// TheBody property of the result. /// TheParameters property of the result. ///This expression if no children changed, or an expression with the updated children. public ExpressionUpdate(Expression body, IEnumerable parameters) { if (body == Body && parameters == Parameters) { return this; } return Expression.Lambda (body, Name, TailCall, parameters); } /// /// Dispatches to the specific visit method for this node type. /// protected internal override Expression Accept(ExpressionVisitor visitor) { return visitor.VisitLambda(this); } internal override LambdaExpression Accept(StackSpiller spiller) { return spiller.Rewrite(this); } internal static LambdaExpression Create(Expression body, string name, bool tailCall, ReadOnlyCollectionparameters) { return new Expression (body, name, tailCall, parameters); } } public partial class Expression { /// /// Creates an Expression{T} given the delegate type. Caches the /// factory method to speed up repeated creations for the same T. /// internal static LambdaExpression CreateLambda(Type delegateType, Expression body, string name, bool tailCall, ReadOnlyCollectionparameters) { // Get or create a delegate to the public Expression.Lambda // method and call that will be used for creating instances of this // delegate type LambdaFactory fastPath; if (_LambdaFactories == null) { // NOTE: this must be Interlocked ----igment since we use _LambdaFactories for locking. Interlocked.CompareExchange(ref _LambdaFactories, new CacheDict (50), null); } MethodInfo create = null; lock (_LambdaFactories) { if (!_LambdaFactories.TryGetValue(delegateType, out fastPath)) { create = typeof(Expression<>).MakeGenericType(delegateType).GetMethod("Create", BindingFlags.Static | BindingFlags.NonPublic); if (TypeUtils.CanCache(delegateType)) { _LambdaFactories[delegateType] = fastPath = (LambdaFactory)Delegate.CreateDelegate(typeof(LambdaFactory), create); } } } if (fastPath != null) { return fastPath(body, name, tailCall, parameters); } Debug.Assert(create != null); return (LambdaExpression)create.Invoke(null, new object[] { body, name, tailCall, parameters }); } /// /// Creates an ///where the delegate type is known at compile time. /// The delegate type. /// Anto set the property equal to. /// An array that contains objects to use to populate the collection. /// An public static Expressionthat has the property equal to and the and properties set to the specified values. Lambda (Expression body, params ParameterExpression[] parameters) { return Lambda (body, false, (IEnumerable )parameters); } /// /// Creates an ///where the delegate type is known at compile time. /// The delegate type. /// Anto set the property equal to. /// A that indicates if tail call optimization will be applied when compiling the created expression. /// An array that contains objects to use to populate the collection. /// An public static Expressionthat has the property equal to and the and properties set to the specified values. Lambda (Expression body, bool tailCall, params ParameterExpression[] parameters) { return Lambda (body, tailCall, (IEnumerable )parameters); } /// /// Creates an ///where the delegate type is known at compile time. /// The delegate type. /// Anto set the property equal to. /// An that contains objects to use to populate the collection. /// An public static Expressionthat has the property equal to and the and properties set to the specified values. Lambda (Expression body, IEnumerable parameters) { return Lambda (body, null, false, parameters); } /// /// Creates an ///where the delegate type is known at compile time. /// The delegate type. /// Anto set the property equal to. /// A that indicates if tail call optimization will be applied when compiling the created expression. /// An that contains objects to use to populate the collection. /// An public static Expressionthat has the property equal to and the and properties set to the specified values. Lambda (Expression body, bool tailCall, IEnumerable parameters) { return Lambda (body, null, tailCall, parameters); } /// /// Creates an ///where the delegate type is known at compile time. /// The delegate type. /// Anto set the property equal to. /// An that contains objects to use to populate the collection. /// The name of the lambda. Used for generating debugging info. /// An public static Expressionthat has the property equal to and the and properties set to the specified values. Lambda (Expression body, String name, IEnumerable parameters) { return Lambda (body, name, false, parameters); } /// /// Creates an ///where the delegate type is known at compile time. /// The delegate type. /// Anto set the property equal to. /// The name of the lambda. Used for generating debugging info. /// An that contains objects to use to populate the collection. /// A that indicates if tail call optimization will be applied when compiling the created expression. /// An public static Expressionthat has the property equal to and the and properties set to the specified values. Lambda (Expression body, String name, bool tailCall, IEnumerable parameters) { var parameterList = parameters.ToReadOnly(); ValidateLambdaArgs(typeof(TDelegate), ref body, parameterList); return new Expression (body, name, tailCall, parameterList); } /// /// Creates a LambdaExpression by first constructing a delegate type. /// /// Anto set the property equal to. /// An array that contains objects to use to populate the collection. /// A public static LambdaExpression Lambda(Expression body, params ParameterExpression[] parameters) { return Lambda(body, false, (IEnumerablethat has the property equal to Lambda and the and properties set to the specified values. )parameters); } /// /// Creates a LambdaExpression by first constructing a delegate type. /// /// Anto set the property equal to. /// A that indicates if tail call optimization will be applied when compiling the created expression. /// An array that contains objects to use to populate the collection. /// A public static LambdaExpression Lambda(Expression body, bool tailCall, params ParameterExpression[] parameters) { return Lambda(body, tailCall, (IEnumerablethat has the property equal to Lambda and the and properties set to the specified values. )parameters); } /// /// Creates a LambdaExpression by first constructing a delegate type. /// /// Anto set the property equal to. /// An that contains objects to use to populate the collection. /// A public static LambdaExpression Lambda(Expression body, IEnumerablethat has the property equal to Lambda and the and properties set to the specified values. parameters) { return Lambda(body, null, false, parameters); } /// /// Creates a LambdaExpression by first constructing a delegate type. /// /// Anto set the property equal to. /// A that indicates if tail call optimization will be applied when compiling the created expression. /// An that contains objects to use to populate the collection. /// A public static LambdaExpression Lambda(Expression body, bool tailCall, IEnumerablethat has the property equal to Lambda and the and properties set to the specified values. parameters) { return Lambda(body, null, tailCall, parameters); } /// /// Creates a LambdaExpression by first constructing a delegate type. /// /// Anto set the property equal to. /// An array that contains objects to use to populate the collection. /// A representing the delegate signature for the lambda. /// A public static LambdaExpression Lambda(Type delegateType, Expression body, params ParameterExpression[] parameters) { return Lambda(delegateType, body, null, false, parameters); } ///that has the property equal to Lambda and the and properties set to the specified values. /// Creates a LambdaExpression by first constructing a delegate type. /// /// Anto set the property equal to. /// A that indicates if tail call optimization will be applied when compiling the created expression. /// An array that contains objects to use to populate the collection. /// A representing the delegate signature for the lambda. /// A public static LambdaExpression Lambda(Type delegateType, Expression body, bool tailCall, params ParameterExpression[] parameters) { return Lambda(delegateType, body, null, tailCall, parameters); } ///that has the property equal to Lambda and the and properties set to the specified values. /// Creates a LambdaExpression by first constructing a delegate type. /// /// Anto set the property equal to. /// An that contains objects to use to populate the collection. /// A representing the delegate signature for the lambda. /// A public static LambdaExpression Lambda(Type delegateType, Expression body, IEnumerablethat has the property equal to Lambda and the and properties set to the specified values. parameters) { return Lambda(delegateType, body, null, false, parameters); } /// /// Creates a LambdaExpression by first constructing a delegate type. /// /// Anto set the property equal to. /// A that indicates if tail call optimization will be applied when compiling the created expression. /// An that contains objects to use to populate the collection. /// A representing the delegate signature for the lambda. /// A public static LambdaExpression Lambda(Type delegateType, Expression body, bool tailCall, IEnumerablethat has the property equal to Lambda and the and properties set to the specified values. parameters) { return Lambda(delegateType, body, null, tailCall, parameters); } /// /// Creates a LambdaExpression by first constructing a delegate type. /// /// Anto set the property equal to. /// An that contains objects to use to populate the collection. /// The name for the lambda. Used for emitting debug information. /// A public static LambdaExpression Lambda(Expression body, string name, IEnumerablethat has the property equal to Lambda and the and properties set to the specified values. parameters) { return Lambda(body, name, false, parameters); } /// /// Creates a LambdaExpression by first constructing a delegate type. /// /// Anto set the property equal to. /// The name for the lambda. Used for emitting debug information. /// A that indicates if tail call optimization will be applied when compiling the created expression. /// An that contains objects to use to populate the collection. /// A public static LambdaExpression Lambda(Expression body, string name, bool tailCall, IEnumerablethat has the property equal to Lambda and the and properties set to the specified values. parameters) { ContractUtils.RequiresNotNull(body, "body"); var parameterList = parameters.ToReadOnly(); int paramCount = parameterList.Count; Type[] typeArgs = new Type[paramCount + 1]; if (paramCount > 0) { var set = new Set (parameterList.Count); for (int i = 0; i < paramCount; i++) { var param = parameterList[i]; ContractUtils.RequiresNotNull(param, "parameter"); typeArgs[i] = param.IsByRef ? param.Type.MakeByRefType() : param.Type; if (set.Contains(param)) { throw Error.DuplicateVariable(param); } set.Add(param); } } typeArgs[paramCount] = body.Type; Type delegateType = DelegateHelpers.MakeDelegateType(typeArgs); return CreateLambda(delegateType, body, name, tailCall, parameterList); } /// /// Creates a LambdaExpression by first constructing a delegate type. /// /// Anto set the property equal to. /// An that contains objects to use to populate the collection. /// The name for the lambda. Used for emitting debug information. /// A representing the delegate signature for the lambda. /// A public static LambdaExpression Lambda(Type delegateType, Expression body, string name, IEnumerablethat has the property equal to Lambda and the and properties set to the specified values. parameters) { var paramList = parameters.ToReadOnly(); ValidateLambdaArgs(delegateType, ref body, paramList); return CreateLambda(delegateType, body, name, false, paramList); } /// /// Creates a LambdaExpression by first constructing a delegate type. /// /// Arepresenting the delegate signature for the lambda. /// An to set the property equal to. /// The name for the lambda. Used for emitting debug information. /// A that indicates if tail call optimization will be applied when compiling the created expression. /// An that contains objects to use to populate the collection. /// A public static LambdaExpression Lambda(Type delegateType, Expression body, string name, bool tailCall, IEnumerablethat has the property equal to Lambda and the and properties set to the specified values. parameters) { var paramList = parameters.ToReadOnly(); ValidateLambdaArgs(delegateType, ref body, paramList); return CreateLambda(delegateType, body, name, tailCall, paramList); } private static void ValidateLambdaArgs(Type delegateType, ref Expression body, ReadOnlyCollection parameters) { ContractUtils.RequiresNotNull(delegateType, "delegateType"); RequiresCanRead(body, "body"); if (!typeof(Delegate).IsAssignableFrom(delegateType) || delegateType == typeof(Delegate)) { throw Error.LambdaTypeMustBeDerivedFromSystemDelegate(); } MethodInfo mi; lock (_LambdaDelegateCache) { if (!_LambdaDelegateCache.TryGetValue(delegateType, out mi)) { mi = delegateType.GetMethod("Invoke"); if (TypeUtils.CanCache(delegateType)) { _LambdaDelegateCache[delegateType] = mi; } } } ParameterInfo[] pis = mi.GetParametersCached(); if (pis.Length > 0) { if (pis.Length != parameters.Count) { throw Error.IncorrectNumberOfLambdaDeclarationParameters(); } var set = new Set (pis.Length); for (int i = 0, n = pis.Length; i < n; i++) { ParameterExpression pex = parameters[i]; ParameterInfo pi = pis[i]; RequiresCanRead(pex, "parameters"); Type pType = pi.ParameterType; if (pex.IsByRef) { if (!pType.IsByRef) { //We cannot pass a parameter of T& to a delegate that takes T or any non-ByRef type. throw Error.ParameterExpressionNotValidAsDelegate(pex.Type.MakeByRefType(), pType); } pType = pType.GetElementType(); } if (!TypeUtils.AreReferenceAssignable(pex.Type, pType)) { throw Error.ParameterExpressionNotValidAsDelegate(pex.Type, pType); } if (set.Contains(pex)) { throw Error.DuplicateVariable(pex); } set.Add(pex); } } else if (parameters.Count > 0) { throw Error.IncorrectNumberOfLambdaDeclarationParameters(); } if (mi.ReturnType != typeof(void) && !TypeUtils.AreReferenceAssignable(mi.ReturnType, body.Type)) { if (TypeUtils.IsSameOrSubclass(typeof(LambdaExpression), mi.ReturnType) && mi.ReturnType.IsAssignableFrom(body.GetType())) { body = Expression.Quote(body); } else { throw Error.ExpressionTypeDoesNotMatchReturn(body.Type, mi.ReturnType); } } } private static bool ValidateTryGetFuncActionArgs(Type[] typeArgs) { if (typeArgs == null) { throw new ArgumentNullException("typeArgs"); } for (int i = 0, n = typeArgs.Length; i < n; i++) { var a = typeArgs[i]; if (a == null) { throw new ArgumentNullException("typeArgs"); } if (a.IsByRef) { return false; } } return true; } /// /// Creates a /// An array of Type objects that specify the type arguments for the System.Func delegate type. ///object that represents a generic System.Func delegate type that has specific type arguments. /// The last type argument specifies the return type of the created delegate. /// The type of a System.Func delegate that has the specified type arguments. public static Type GetFuncType(params Type[] typeArgs) { if (!ValidateTryGetFuncActionArgs(typeArgs)) throw Error.TypeMustNotBeByRef(); Type result = DelegateHelpers.GetFuncType(typeArgs); if (result == null) { throw Error.IncorrectNumberOfTypeArgsForFunc(); } return result; } ////// Creates a /// An array of Type objects that specify the type arguments for the System.Func delegate type. /// When this method returns, contains the generic System.Func delegate type that has specific type arguments. Contains null if there is no generic System.Func delegate that matches theobject that represents a generic System.Func delegate type that has specific type arguments. /// The last type argument specifies the return type of the created delegate. /// .This parameter is passed uninitialized. /// true if generic System.Func delegate type was created for specific public static bool TryGetFuncType(Type[] typeArgs, out Type funcType) { if (ValidateTryGetFuncActionArgs(typeArgs)) { return (funcType = DelegateHelpers.GetFuncType(typeArgs)) != null; } funcType = null; return false; } ///; false otherwise. /// Creates a /// An array of Type objects that specify the type arguments for the System.Action delegate type. ///object that represents a generic System.Action delegate type that has specific type arguments. /// The type of a System.Action delegate that has the specified type arguments. public static Type GetActionType(params Type[] typeArgs) { if (!ValidateTryGetFuncActionArgs(typeArgs)) throw Error.TypeMustNotBeByRef(); Type result = DelegateHelpers.GetActionType(typeArgs); if (result == null) { throw Error.IncorrectNumberOfTypeArgsForAction(); } return result; } ////// Creates a /// An array of Type objects that specify the type arguments for the System.Action delegate type. /// When this method returns, contains the generic System.Action delegate type that has specific type arguments. Contains null if there is no generic System.Action delegate that matches theobject that represents a generic System.Action delegate type that has specific type arguments. /// .This parameter is passed uninitialized. /// true if generic System.Action delegate type was created for specific public static bool TryGetActionType(Type[] typeArgs, out Type actionType) { if (ValidateTryGetFuncActionArgs(typeArgs)) { return (actionType = DelegateHelpers.GetActionType(typeArgs)) != null; } actionType = null; return false; } ///; false otherwise. /// Gets a /// The type arguments of the delegate. ///object that represents a generic System.Func or System.Action delegate type that has specific type arguments. /// The last type argument determines the return type of the delegate. If no Func or Action is large enough, it will generate a custom /// delegate type. /// The delegate type. ////// As with Func, the last argument is the return type. It can be set /// to System.Void to produce an Action. public static Type GetDelegateType(params Type[] typeArgs) { ContractUtils.RequiresNotEmpty(typeArgs, "typeArgs"); ContractUtils.RequiresNotNullItems(typeArgs, "typeArgs"); return DelegateHelpers.MakeDelegateType(typeArgs); } } } // 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
- QuaternionAnimationBase.cs
- AsyncSerializedWorker.cs
- ToolStrip.cs
- ActivatedMessageQueue.cs
- DataControlFieldTypeEditor.cs
- LayoutEvent.cs
- TemplateField.cs
- BitmapDecoder.cs
- XmlSerializerFaultFormatter.cs
- _UncName.cs
- PrincipalPermission.cs
- SqlInternalConnectionTds.cs
- ZipFileInfo.cs
- TimeSpanMinutesOrInfiniteConverter.cs
- XamlNamespaceHelper.cs
- DataGridViewBand.cs
- WebSysDefaultValueAttribute.cs
- ConfigurationProperty.cs
- Help.cs
- ExecutedRoutedEventArgs.cs
- FillBehavior.cs
- WebPermission.cs
- GlobalAllocSafeHandle.cs
- CannotUnloadAppDomainException.cs
- ConfigWriter.cs
- ComPlusContractBehavior.cs
- MimeBasePart.cs
- SynchronizedInputHelper.cs
- InfoCardProofToken.cs
- x509utils.cs
- Utils.cs
- ExpandCollapseIsCheckedConverter.cs
- ImageSource.cs
- HtmlInputButton.cs
- DoubleConverter.cs
- TextTreeUndo.cs
- Debugger.cs
- PreviewPageInfo.cs
- TraceHandlerErrorFormatter.cs
- WindowsListViewItemStartMenu.cs
- ImageFormatConverter.cs
- CacheManager.cs
- MetadataReference.cs
- CellConstantDomain.cs
- Scheduler.cs
- DataColumnPropertyDescriptor.cs
- BrowserDefinitionCollection.cs
- RepeatBehavior.cs
- OdbcReferenceCollection.cs
- WebControl.cs
- SpeechEvent.cs
- PathData.cs
- VariantWrapper.cs
- ListViewTableCell.cs
- GlobalDataBindingHandler.cs
- DES.cs
- Literal.cs
- MenuItem.cs
- XmlMtomReader.cs
- PreviewPageInfo.cs
- TableRowCollection.cs
- ServiceProviders.cs
- MatrixAnimationUsingKeyFrames.cs
- DataAdapter.cs
- SelectionUIService.cs
- FlowStep.cs
- AccessDataSourceDesigner.cs
- RawStylusActions.cs
- DataControlFieldHeaderCell.cs
- SpecialFolderEnumConverter.cs
- UnmanagedBitmapWrapper.cs
- AccessedThroughPropertyAttribute.cs
- SqlCommand.cs
- WindowsGraphicsCacheManager.cs
- DataGridViewRowHeaderCell.cs
- InstanceBehavior.cs
- EncoderFallback.cs
- PropertyGroupDescription.cs
- DataControlPagerLinkButton.cs
- AppDomainProtocolHandler.cs
- ObjectViewEntityCollectionData.cs
- ToolStripItemDesigner.cs
- NullableDecimalSumAggregationOperator.cs
- FixedDSBuilder.cs
- DataGridBeginningEditEventArgs.cs
- _StreamFramer.cs
- RightsManagementInformation.cs
- TemplateNodeContextMenu.cs
- MethodResolver.cs
- JapaneseCalendar.cs
- PersistChildrenAttribute.cs
- CannotUnloadAppDomainException.cs
- InvalidOperationException.cs
- IdentityModelDictionary.cs
- OpCodes.cs
- Configuration.cs
- ExpressionBindingCollection.cs
- InvalidComObjectException.cs
- SendMessageChannelCache.cs
- MessageHeaderException.cs