ExpressionEvaluator.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / Orcas / SP / ndp / fx / src / DataEntity / System / Data / Objects / ELinq / ExpressionEvaluator.cs / 3 / ExpressionEvaluator.cs

                            //---------------------------------------------------------------------- 
// 
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// 
// @owner  [....]
//--------------------------------------------------------------------- 
 
using System.Linq.Expressions;
using System.Diagnostics; 
using System.Reflection;
using System.Linq;
using System.Data.Metadata.Edm;
using System.Collections.Generic; 
namespace System.Data.Objects.ELinq
{ 
    ///  
    /// Class handling in-memory translation of expressions that are
    /// not supported through the standard LINQ translation. Supports 
    /// only expressions that can be efficiently evaluated at runtime.
    /// 
    internal static class ExpressionEvaluator
    { 
        private static readonly IQueryProvider s_compilerQueryService =
            Enumerable.Empty().AsQueryable().Provider; 
 

        ///  
        /// For CompiledQuery, handles sub-expressions of the form:
        ///
        ///     ctx.ObjectQueryProperty
        /// 
        /// where ctx is the context parameter, e.g.:
        /// 
        ///     CompiledQuery.Compile((ctx, ...) => ctx...) 
        ///
        /// NOTE: this method assumes that all client evaluatable nodes have been evaluated 
        ///
        /// 
        internal static bool TryEvaluateRootQuery(BindingContext bindingContext, Expression expression, out ObjectQuery rootQuery)
        { 
            rootQuery = null;
            if (bindingContext.ObjectContext == null) 
            { 
                // there is no root context parameter, so the expression can't match
                return false; 
            }

            if (!typeof(ObjectQuery).IsAssignableFrom(expression.Type))
            { 
                // if the expression doesn't return an ObjectQuery<>, it can't match the pattern
                return false; 
            } 

            Expression currentExpression = expression; 

            // check that the remaining expression is of the form ctx.ObjectQueryProperty
            if (currentExpression.NodeType != ExpressionType.MemberAccess) { return false; }
 
            var memberExpression = (MemberExpression)currentExpression;
 
            currentExpression = memberExpression.Expression; 
            if (null == currentExpression || currentExpression.NodeType != ExpressionType.Parameter) { return false; }
 
            ParameterExpression parameterExpression = (ParameterExpression)currentExpression;
            if (!bindingContext.IsRootContextParameter(parameterExpression)) { return false; }

            var queryCreator = (IRootQueryCreator)Activator.CreateInstance(typeof(RootQueryCreator<,>).MakeGenericType( 
                parameterExpression.Type, expression.Type));
            rootQuery = queryCreator.Invoke(expression, parameterExpression, bindingContext.ObjectContext); 
            return true; 
        }
 
        [Conditional("DEBUG")]
        private static void DebugOnlyVerifyMethodOverloadCount(Type type, string methodName, int expectedCount)
        {
            int count = 0; 
            foreach (var m in type.GetMethods())
            { 
                if (m.Name == methodName) 
                {
                    count++; 
                }
            }

            Debug.Assert(count == expectedCount, "Did you add a new " + methodName + " overload?"); 
        }
 
        ///  
        /// Evaluates the given expression using the default in-memory compiler.
        ///  
        /// Expression to evaluate. Must not be null.
        /// Result of evaluating the expression.
        internal static object EvaluateExpression(Expression expression)
        { 
            return s_compilerQueryService.Execute(expression);
        } 
 
        // this method is only correct when returning true
        // if you have also determined that all the nodes below it 
        // also return true
        internal static bool IsExpressionNodeClientEvaluatable(Expression expression)
        {
            if (null == expression) { return false; } 
            switch (expression.NodeType)
            { 
                case ExpressionType.New: 
                    {
                        // support construction of primitive types 
                        PrimitiveType primitiveType;
                        if (!ClrProviderManifest.Instance.TryGetPrimitiveType(TypeSystem.GetNonNullableType(expression.Type),
                            out primitiveType))
                        { 
                            return false;
                        } 
                        return true; 
                    }
                case ExpressionType.Constant: 
                    return true;
                case ExpressionType.NewArrayInit:
                    {
                        // allow initialization of byte[] 'literals' 
                        return (typeof(byte[]) == expression.Type);
                    } 
                case ExpressionType.Convert: 
                    {
                        return true; 
                    }
                default:
                    return false;
            } 
        }
 
        // this method is only correct when returning true 
        // if you have also determined that all the nodes below it
        // also return true from (IsExpressionNodeAClosure || IsExpressionNodeClientEvaluatable) 
        internal static bool IsExpressionNodeAClosure(Expression expression)
        {
            Debug.Assert(null != expression);
            if (ExpressionType.MemberAccess == expression.NodeType) 
            {
                MemberExpression memberExpression = (MemberExpression)expression; 
                if (memberExpression.Member.MemberType == MemberTypes.Property) 
                {
                    return !(ExpressionConverter.CanTranslatePropertyInfo((PropertyInfo)memberExpression.Member)); 
                }
                return true;
            }
            return false; 

        } 
 
        private interface IRootQueryCreator
        { 
            ObjectQuery Invoke(Expression body, ParameterExpression parameter, ObjectContext objectContext);
        }

        private class RootQueryCreator : IRootQueryCreator 
            where T_Context : ObjectContext
            where T_ObjectQuery : ObjectQuery 
        { 
            public ObjectQuery Invoke(Expression body, ParameterExpression parameter, ObjectContext objectContext)
            { 
                return Expression.Lambda>(body, parameter).Compile()((T_Context)objectContext);
            }
        }
    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//---------------------------------------------------------------------- 
// 
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// 
// @owner  [....]
//--------------------------------------------------------------------- 
 
using System.Linq.Expressions;
using System.Diagnostics; 
using System.Reflection;
using System.Linq;
using System.Data.Metadata.Edm;
using System.Collections.Generic; 
namespace System.Data.Objects.ELinq
{ 
    ///  
    /// Class handling in-memory translation of expressions that are
    /// not supported through the standard LINQ translation. Supports 
    /// only expressions that can be efficiently evaluated at runtime.
    /// 
    internal static class ExpressionEvaluator
    { 
        private static readonly IQueryProvider s_compilerQueryService =
            Enumerable.Empty().AsQueryable().Provider; 
 

        ///  
        /// For CompiledQuery, handles sub-expressions of the form:
        ///
        ///     ctx.ObjectQueryProperty
        /// 
        /// where ctx is the context parameter, e.g.:
        /// 
        ///     CompiledQuery.Compile((ctx, ...) => ctx...) 
        ///
        /// NOTE: this method assumes that all client evaluatable nodes have been evaluated 
        ///
        /// 
        internal static bool TryEvaluateRootQuery(BindingContext bindingContext, Expression expression, out ObjectQuery rootQuery)
        { 
            rootQuery = null;
            if (bindingContext.ObjectContext == null) 
            { 
                // there is no root context parameter, so the expression can't match
                return false; 
            }

            if (!typeof(ObjectQuery).IsAssignableFrom(expression.Type))
            { 
                // if the expression doesn't return an ObjectQuery<>, it can't match the pattern
                return false; 
            } 

            Expression currentExpression = expression; 

            // check that the remaining expression is of the form ctx.ObjectQueryProperty
            if (currentExpression.NodeType != ExpressionType.MemberAccess) { return false; }
 
            var memberExpression = (MemberExpression)currentExpression;
 
            currentExpression = memberExpression.Expression; 
            if (null == currentExpression || currentExpression.NodeType != ExpressionType.Parameter) { return false; }
 
            ParameterExpression parameterExpression = (ParameterExpression)currentExpression;
            if (!bindingContext.IsRootContextParameter(parameterExpression)) { return false; }

            var queryCreator = (IRootQueryCreator)Activator.CreateInstance(typeof(RootQueryCreator<,>).MakeGenericType( 
                parameterExpression.Type, expression.Type));
            rootQuery = queryCreator.Invoke(expression, parameterExpression, bindingContext.ObjectContext); 
            return true; 
        }
 
        [Conditional("DEBUG")]
        private static void DebugOnlyVerifyMethodOverloadCount(Type type, string methodName, int expectedCount)
        {
            int count = 0; 
            foreach (var m in type.GetMethods())
            { 
                if (m.Name == methodName) 
                {
                    count++; 
                }
            }

            Debug.Assert(count == expectedCount, "Did you add a new " + methodName + " overload?"); 
        }
 
        ///  
        /// Evaluates the given expression using the default in-memory compiler.
        ///  
        /// Expression to evaluate. Must not be null.
        /// Result of evaluating the expression.
        internal static object EvaluateExpression(Expression expression)
        { 
            return s_compilerQueryService.Execute(expression);
        } 
 
        // this method is only correct when returning true
        // if you have also determined that all the nodes below it 
        // also return true
        internal static bool IsExpressionNodeClientEvaluatable(Expression expression)
        {
            if (null == expression) { return false; } 
            switch (expression.NodeType)
            { 
                case ExpressionType.New: 
                    {
                        // support construction of primitive types 
                        PrimitiveType primitiveType;
                        if (!ClrProviderManifest.Instance.TryGetPrimitiveType(TypeSystem.GetNonNullableType(expression.Type),
                            out primitiveType))
                        { 
                            return false;
                        } 
                        return true; 
                    }
                case ExpressionType.Constant: 
                    return true;
                case ExpressionType.NewArrayInit:
                    {
                        // allow initialization of byte[] 'literals' 
                        return (typeof(byte[]) == expression.Type);
                    } 
                case ExpressionType.Convert: 
                    {
                        return true; 
                    }
                default:
                    return false;
            } 
        }
 
        // this method is only correct when returning true 
        // if you have also determined that all the nodes below it
        // also return true from (IsExpressionNodeAClosure || IsExpressionNodeClientEvaluatable) 
        internal static bool IsExpressionNodeAClosure(Expression expression)
        {
            Debug.Assert(null != expression);
            if (ExpressionType.MemberAccess == expression.NodeType) 
            {
                MemberExpression memberExpression = (MemberExpression)expression; 
                if (memberExpression.Member.MemberType == MemberTypes.Property) 
                {
                    return !(ExpressionConverter.CanTranslatePropertyInfo((PropertyInfo)memberExpression.Member)); 
                }
                return true;
            }
            return false; 

        } 
 
        private interface IRootQueryCreator
        { 
            ObjectQuery Invoke(Expression body, ParameterExpression parameter, ObjectContext objectContext);
        }

        private class RootQueryCreator : IRootQueryCreator 
            where T_Context : ObjectContext
            where T_ObjectQuery : ObjectQuery 
        { 
            public ObjectQuery Invoke(Expression body, ParameterExpression parameter, ObjectContext objectContext)
            { 
                return Expression.Lambda>(body, parameter).Compile()((T_Context)objectContext);
            }
        }
    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK