FunctionDescription.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / Orcas / NetFXw7 / ndp / fx / src / DataWeb / Server / System / Data / Services / Parsing / FunctionDescription.cs / 1 / FunctionDescription.cs

                            //---------------------------------------------------------------------- 
// 
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//  
//      Provides a class to represent system functions.
//  
// 
// @owner  [....]
//--------------------------------------------------------------------- 

namespace System.Data.Services.Parsing
{
    using System; 
    using System.Collections.Generic;
    using System.Diagnostics; 
    using System.Linq.Expressions; 
    using System.Reflection;
 
    /// Use this class to represent a system function for Astoria expressions.
    [DebuggerDisplay("FunctionDescription {name}")]
    internal class FunctionDescription
    { 
        /// Function name for type casts.
        private const string FunctionNameCast = "cast"; 
 
        /// Function name for type checks.
        private const string FunctionNameIsOf = "isof"; 

        /// CLR member for property or method invocation.
        private readonly MemberInfo member;
 
        /// Function name.
        private readonly string name; 
 
        /// Parameter types for method invocation.
        private readonly Type[] parameterTypes; 

        /// Conversion to expression for this function.
        private Func conversionFunction;
 
        /// Initializes a new .
        /// CLR member for property or method invocation. 
        /// Parameter types for method invocation. 
        public FunctionDescription(MemberInfo member, Type[] parameterTypes)
            : this(member, parameterTypes, null, member.Name) 
        {
        }

        /// Initializes a new . 
        /// Name for conversion function.
        /// Parameter types for method invocation. 
        /// Conversion to expression for this function. 
        public FunctionDescription(string name, Type[] parameterTypes, Func conversionFunction)
            : this(null, parameterTypes, conversionFunction, name) 
        {
        }

        /// Initializes a new . 
        /// CLR member for property or method invocation.
        /// Parameter types for method invocation. 
        /// Conversion to expression for this function. 
        /// Name for conversion function.
        private FunctionDescription( 
            MemberInfo member,
            Type[] parameterTypes,
            Func conversionFunction,
            string name) 
        {
            this.member = member; 
            this.parameterTypes = parameterTypes; 
            this.conversionFunction = conversionFunction;
            this.name = name; 
        }

        /// Conversion to expression for this function.
        public Func ConversionFunction 
        {
            [DebuggerStepThrough] 
            get { return this.conversionFunction; } 
            [DebuggerStepThrough]
            set { this.conversionFunction = value; } 
        }

        /// Gets a value indicating whether this function is a typecast function.
        public bool IsTypeCast 
        {
            get { return this.name == FunctionNameCast; } 
        } 

        /// Gets a value indicating whether this function is a type check function. 
        public bool IsTypeCheck
        {
            get { return this.name == FunctionNameIsOf; }
        } 

        /// Parameter types for method invocation. 
        public Type[] ParameterTypes 
        {
            [DebuggerStepThrough] 
            get { return this.parameterTypes; }
        }

        /// Performs an instance method invocation. 
        /// "it" expression; unused by this function.
        /// Arguments for method invocation; first one should be the target 'this'. 
        /// A new expression with the method invocation. 
        public Expression InstanceMethodConvertionFunction(Expression target, Expression[] arguments)
        { 
            Expression instanceArgument = arguments[0];
            Expression[] methodArguments = new Expression[arguments.Length - 1];
            Array.Copy(arguments, 1, methodArguments, 0, arguments.Length - 1);
            return Expression.Call(instanceArgument, (MethodInfo)this.member, methodArguments); 
        }
 
        /// Performs a static method invocation. 
        /// "it" expression; unused by this function.
        /// Arguments for method invocation. 
        /// A new expression with the method invocation.
        public Expression StaticMethodConvertionFunction(Expression target, Expression[] arguments)
        {
            return Expression.Call((MethodInfo)this.member, arguments); 
        }
 
        /// Performs an instance property access. 
        /// "it" expression; unused by this function.
        /// Argument for property access; instance. 
        /// A new expression with the property access.
        public Expression InstancePropertyConvertionFunction(Expression target, Expression[] arguments)
        {
            return Expression.Property(arguments[0], (PropertyInfo)this.member); 
        }
 
        /// Builds a list of function signatures. 
        /// Function name.
        /// Function descriptions. 
        /// A string with ';'-separated list of function signatures.
        internal static string BuildSignatureList(string name, IEnumerable descriptions)
        {
            System.Text.StringBuilder builder = new System.Text.StringBuilder(); 
            string descriptionSeparator = "";
            foreach (FunctionDescription description in descriptions) 
            { 
                builder.Append(descriptionSeparator);
                descriptionSeparator = "; "; 

                string parameterSeparator = "";
                builder.Append(name);
                builder.Append('('); 
                foreach (Type type in description.ParameterTypes)
                { 
                    builder.Append(parameterSeparator); 
                    parameterSeparator = ", ";
 
                    Type underlyingType = Nullable.GetUnderlyingType(type);
                    if (underlyingType != null)
                    {
                        builder.Append(underlyingType.FullName); 
                        builder.Append('?');
                    } 
                    else 
                    {
                        builder.Append(type.FullName); 
                    }
                }

                builder.Append(')'); 
            }
 
            return builder.ToString(); 
        }
 
        /// Creates and populates a dictionary of system functions.
        /// A new dictionary of functions.
        internal static Dictionary CreateFunctions()
        { 
            Dictionary result = new Dictionary(StringComparer.Ordinal);
 
            // String functions. 
            FunctionDescription[] signatures;
            result.Add("endswith", new FunctionDescription[] { StringInstanceFunction("EndsWith", typeof(string)) }); 
            result.Add("indexof", new FunctionDescription[] { StringInstanceFunction("IndexOf", typeof(string)) });
            result.Add("replace", new FunctionDescription[] { StringInstanceFunction("Replace", typeof(string), typeof(string)) });
            result.Add("startswith", new FunctionDescription[] { StringInstanceFunction("StartsWith", typeof(string)) });
            result.Add("tolower", new FunctionDescription[] { StringInstanceFunction("ToLower", Type.EmptyTypes) }); 
            result.Add("toupper", new FunctionDescription[] { StringInstanceFunction("ToUpper", Type.EmptyTypes) });
            result.Add("trim", new FunctionDescription[] { StringInstanceFunction("Trim", Type.EmptyTypes) }); 
 
            signatures = new FunctionDescription[]
            { 
                StringInstanceFunction("Substring", typeof(int)),
                StringInstanceFunction("Substring", typeof(int), typeof(int))
            };
            result.Add("substring", signatures); 

            signatures = new FunctionDescription[] 
            { 
                new FunctionDescription("substringof", new Type[] { typeof(string), typeof(string) }, SubstringOf)
            }; 
            result.Add("substringof", signatures);

            signatures = new FunctionDescription[]
            { 
                CreateFunctionDescription(typeof(string), false /* instance */, true /* method */, "Concat", typeof(string), typeof(string))
            }; 
            result.Add("concat", signatures); 

            signatures = new FunctionDescription[] 
            {
                CreateFunctionDescription(typeof(string), true /* instance */, false /* method */, "Length", Type.EmptyTypes)
            };
            result.Add("length", signatures); 

            // DateTime functions. 
            result.Add("year", DateTimeFunctionArray("Year")); 
            result.Add("month", DateTimeFunctionArray("Month"));
            result.Add("day", DateTimeFunctionArray("Day")); 
            result.Add("hour", DateTimeFunctionArray("Hour"));
            result.Add("minute", DateTimeFunctionArray("Minute"));
            result.Add("second", DateTimeFunctionArray("Second"));
 
            // Mathematical functions.
            result.Add("round", MathFunctionArray("Round")); 
            result.Add("floor", MathFunctionArray("Floor")); 
            result.Add("ceiling", MathFunctionArray("Ceiling"));
 
            // Type functions.
            signatures = new FunctionDescription[]
            {
                new FunctionDescription(FunctionNameIsOf, new Type[] { typeof(Type) }, new Func(FunctionDescription.UnaryIsOf)), 
                new FunctionDescription(FunctionNameIsOf, new Type[] { typeof(object), typeof(Type) }, new Func(FunctionDescription.BinaryIsOf)),
            }; 
            result.Add(FunctionNameIsOf, signatures); 

            // For cast() signatures, we need to add all primitive types directly as well as the object (open type) 
            // and unary versions; otherwise expression will convert to object, then again to whatever other type
            // is required.
            System.Data.Services.Providers.ResourceType[] primitiveTypes = WebUtil.GetPrimitiveTypes();
            List castSignatures = new List(2 + primitiveTypes.Length * 2); 
            for (int i = 0; i < primitiveTypes.Length; i++)
            { 
                Debug.Assert( 
                    primitiveTypes[i].Type != typeof(Type),
                    "primitiveTypes[i].Type != typeof(Type) -- otherwise extra signatures will be added for cast()"); 
                Debug.Assert(
                    primitiveTypes[i].Type != typeof(object),
                    "primitiveTypes[i].Type != typeof(object) -- otherwise extra signatures will be added for cast()");
                castSignatures.Add(new FunctionDescription( 
                    FunctionNameCast,
                    new Type[] { primitiveTypes[i].Type, typeof(Type) }, 
                    new Func(FunctionDescription.BinaryCast))); 
                if (primitiveTypes[i].Type.IsValueType)
                { 
                    castSignatures.Add(new FunctionDescription(
                        FunctionNameCast,
                        new Type[] { typeof(Nullable<>).MakeGenericType(primitiveTypes[i].Type), typeof(Type) },
                        new Func(FunctionDescription.BinaryCast))); 
                }
            } 
 
            castSignatures.Add(
                new FunctionDescription(FunctionNameCast, new Type[] { typeof(Type) }, FunctionDescription.UnaryCast)); 
            castSignatures.Add(
                new FunctionDescription(FunctionNameCast, new Type[] { typeof(object), typeof(Type) }, new Func(FunctionDescription.BinaryCast)));

            result.Add(FunctionNameCast, castSignatures.ToArray()); 

            return result; 
        } 

        /// Transforms a URI-style "substringof(a,b)" function into "a.contains(b)". 
        /// Target of query; not used.
        /// Arguments to function.
        /// The conversion for this method.
        internal static Expression SubstringOf(Expression target, Expression[] arguments) 
        {
            Debug.Assert(arguments != null, "arguments != null"); 
            Debug.Assert(arguments.Length == 2, "arguments.Length == 2"); 

            BindingFlags flags = BindingFlags.Public | BindingFlags.Instance; 
            Type[] parameterTypes = new Type[] { typeof(string) };
            MethodInfo method = typeof(string).GetMethod("Contains", flags, null, parameterTypes, null);
            Debug.Assert(method != null, "method != null -- otherwise couldn't find string.Contains(string)");
            return Expression.Call(arguments[1], method, arguments[0]); 
        }
 
        /// Performs a type check for the "it" expression. 
        /// "it" expression.
        /// Argument for type check; type. 
        /// A new expression with the type check.
        internal static Expression UnaryIsOf(Expression target, Expression[] arguments)
        {
            ConstantExpression ce = (ConstantExpression)arguments[0]; 
            return Expression.TypeIs(target, (Type)ce.Value);
        } 
 
        /// Performs a type check for a given expression.
        /// "it" expression; unused by this function. 
        /// Arguments for type check; instance and type.
        /// A new expression with the type check.
        internal static Expression BinaryIsOf(Expression target, Expression[] arguments)
        { 
            ConstantExpression ce = (ConstantExpression)arguments[1];
            return Expression.TypeIs(arguments[0], (Type)ce.Value); 
        } 

        /// Performs a cast for the "it" expression. 
        /// "it" expression.
        /// Argument for cast; type.
        /// A new expression with the cast.
        internal static Expression UnaryCast(Expression target, Expression[] arguments) 
        {
            Debug.Assert(arguments.Length == 1, "arguments.Length == 1"); 
            ConstantExpression ce = (ConstantExpression)arguments[0]; 
            return Expression.Convert(target, (Type)ce.Value);
        } 

        /// Performs a cast for a given expression.
        /// "it" expression; unused by this function.
        /// Arguments for cast; instance and type. 
        /// A new expression with the cast.
        internal static Expression BinaryCast(Expression target, Expression[] arguments) 
        { 
            Debug.Assert(arguments.Length == 2, "arguments.Length == 2");
            ConstantExpression ce = (ConstantExpression)arguments[1]; 

            // Work around for SQLBUDT #615702 - Protocol: exception thrown in XML with filter=null
            //
            // We need this in place so we can recognize null constant reliably and generate 
            // trees that work for both LINQ to Entities and LINQ to Objects for the cases where
            // conversions of null literals generate expressions that don't guard for nulls in the 
            // EF case, but EF ends up calling them anyway because they can be evaluated on the client. 
            Type targetType = (Type)ce.Value;
            if (RequestQueryParser.IsNullConstant(arguments[0])) 
            {
                targetType = RequestQueryParser.GetTypeAllowingNull(targetType);
                return Expression.Constant(null, targetType);
            } 

            return Expression.Convert(arguments[0], targetType); 
        } 

        /// Creates a new function description for a method or property. 
        /// Type on which property or method is declared.
        /// Whether an instance member is looked for.
        /// Whether a method (rather than a property) is looked for.
        /// Name of member. 
        /// Parameter types.
        /// A new function description. 
        private static FunctionDescription CreateFunctionDescription( 
            Type targetType,
            bool instance, 
            bool method,
            string name,
            params Type[] parameterTypes)
        { 
            Debug.Assert(targetType != null, "targetType != null");
            Debug.Assert(name != null, "name != null"); 
            Debug.Assert(parameterTypes.Length == 0 || method, "parameterTypes.Length == 0 || method"); 
            Debug.Assert(method || instance, "method || instance");
 
            BindingFlags flags = BindingFlags.Public | (instance ? BindingFlags.Instance : BindingFlags.Static);
            MemberInfo member;

            if (method) 
            {
                member = targetType.GetMethod(name, flags, null, parameterTypes, null); 
                Debug.Assert(member != null, "methodInfo != null"); 
            }
            else 
            {
                member = targetType.GetProperty(name, flags);
                Debug.Assert(member != null, "propertyInfo != null");
            } 

            Type[] functionParameterTypes; 
            if (instance) 
            {
                functionParameterTypes = new Type[parameterTypes.Length + 1]; 
                functionParameterTypes[0] = targetType;
                parameterTypes.CopyTo(functionParameterTypes, 1);
            }
            else 
            {
                functionParameterTypes = parameterTypes; 
            } 

            FunctionDescription result = new FunctionDescription(member, functionParameterTypes); 
            if (method)
            {
                if (instance)
                { 
                    result.ConversionFunction = new Func(result.InstanceMethodConvertionFunction);
                } 
                else 
                {
                    result.ConversionFunction = new Func(result.StaticMethodConvertionFunction); 
                }
            }
            else
            { 
                Debug.Assert(instance, "instance");
                result.ConversionFunction = new Func(result.InstancePropertyConvertionFunction); 
            } 

            return result; 
        }

        /// Creates a description for a string instance method.
        /// Name of method to look up. 
        /// Parameter types to match.
        /// A new function description. 
        private static FunctionDescription StringInstanceFunction(string name, params Type[] parameterTypes) 
        {
            return CreateFunctionDescription(typeof(string), true /* instance */, true /* method */, name, parameterTypes); 
        }

        /// Creates an array of function description for a DateTime property.
        /// Name of property to look up. 
        /// A new function description array.
        private static FunctionDescription[] DateTimeFunctionArray(string name) 
        { 
            return new FunctionDescription[]
            { 
                CreateFunctionDescription(typeof(DateTime), true /* instance */, false /* method */, name, Type.EmptyTypes)
            };
        }
 
        /// Creates an array of function description for math method with decimal and double overloads.
        /// Name of method to look up. 
        /// A new function description array. 
        private static FunctionDescription[] MathFunctionArray(string name)
        { 
            return new FunctionDescription[]
            {
                CreateFunctionDescription(typeof(Math), false /* instance */, true /* method */, name, typeof(double)),
                CreateFunctionDescription(typeof(Math), false /* instance */, true /* method */, name, typeof(decimal)), 
            };
        } 
    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//---------------------------------------------------------------------- 
// 
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//  
//      Provides a class to represent system functions.
//  
// 
// @owner  [....]
//--------------------------------------------------------------------- 

namespace System.Data.Services.Parsing
{
    using System; 
    using System.Collections.Generic;
    using System.Diagnostics; 
    using System.Linq.Expressions; 
    using System.Reflection;
 
    /// Use this class to represent a system function for Astoria expressions.
    [DebuggerDisplay("FunctionDescription {name}")]
    internal class FunctionDescription
    { 
        /// Function name for type casts.
        private const string FunctionNameCast = "cast"; 
 
        /// Function name for type checks.
        private const string FunctionNameIsOf = "isof"; 

        /// CLR member for property or method invocation.
        private readonly MemberInfo member;
 
        /// Function name.
        private readonly string name; 
 
        /// Parameter types for method invocation.
        private readonly Type[] parameterTypes; 

        /// Conversion to expression for this function.
        private Func conversionFunction;
 
        /// Initializes a new .
        /// CLR member for property or method invocation. 
        /// Parameter types for method invocation. 
        public FunctionDescription(MemberInfo member, Type[] parameterTypes)
            : this(member, parameterTypes, null, member.Name) 
        {
        }

        /// Initializes a new . 
        /// Name for conversion function.
        /// Parameter types for method invocation. 
        /// Conversion to expression for this function. 
        public FunctionDescription(string name, Type[] parameterTypes, Func conversionFunction)
            : this(null, parameterTypes, conversionFunction, name) 
        {
        }

        /// Initializes a new . 
        /// CLR member for property or method invocation.
        /// Parameter types for method invocation. 
        /// Conversion to expression for this function. 
        /// Name for conversion function.
        private FunctionDescription( 
            MemberInfo member,
            Type[] parameterTypes,
            Func conversionFunction,
            string name) 
        {
            this.member = member; 
            this.parameterTypes = parameterTypes; 
            this.conversionFunction = conversionFunction;
            this.name = name; 
        }

        /// Conversion to expression for this function.
        public Func ConversionFunction 
        {
            [DebuggerStepThrough] 
            get { return this.conversionFunction; } 
            [DebuggerStepThrough]
            set { this.conversionFunction = value; } 
        }

        /// Gets a value indicating whether this function is a typecast function.
        public bool IsTypeCast 
        {
            get { return this.name == FunctionNameCast; } 
        } 

        /// Gets a value indicating whether this function is a type check function. 
        public bool IsTypeCheck
        {
            get { return this.name == FunctionNameIsOf; }
        } 

        /// Parameter types for method invocation. 
        public Type[] ParameterTypes 
        {
            [DebuggerStepThrough] 
            get { return this.parameterTypes; }
        }

        /// Performs an instance method invocation. 
        /// "it" expression; unused by this function.
        /// Arguments for method invocation; first one should be the target 'this'. 
        /// A new expression with the method invocation. 
        public Expression InstanceMethodConvertionFunction(Expression target, Expression[] arguments)
        { 
            Expression instanceArgument = arguments[0];
            Expression[] methodArguments = new Expression[arguments.Length - 1];
            Array.Copy(arguments, 1, methodArguments, 0, arguments.Length - 1);
            return Expression.Call(instanceArgument, (MethodInfo)this.member, methodArguments); 
        }
 
        /// Performs a static method invocation. 
        /// "it" expression; unused by this function.
        /// Arguments for method invocation. 
        /// A new expression with the method invocation.
        public Expression StaticMethodConvertionFunction(Expression target, Expression[] arguments)
        {
            return Expression.Call((MethodInfo)this.member, arguments); 
        }
 
        /// Performs an instance property access. 
        /// "it" expression; unused by this function.
        /// Argument for property access; instance. 
        /// A new expression with the property access.
        public Expression InstancePropertyConvertionFunction(Expression target, Expression[] arguments)
        {
            return Expression.Property(arguments[0], (PropertyInfo)this.member); 
        }
 
        /// Builds a list of function signatures. 
        /// Function name.
        /// Function descriptions. 
        /// A string with ';'-separated list of function signatures.
        internal static string BuildSignatureList(string name, IEnumerable descriptions)
        {
            System.Text.StringBuilder builder = new System.Text.StringBuilder(); 
            string descriptionSeparator = "";
            foreach (FunctionDescription description in descriptions) 
            { 
                builder.Append(descriptionSeparator);
                descriptionSeparator = "; "; 

                string parameterSeparator = "";
                builder.Append(name);
                builder.Append('('); 
                foreach (Type type in description.ParameterTypes)
                { 
                    builder.Append(parameterSeparator); 
                    parameterSeparator = ", ";
 
                    Type underlyingType = Nullable.GetUnderlyingType(type);
                    if (underlyingType != null)
                    {
                        builder.Append(underlyingType.FullName); 
                        builder.Append('?');
                    } 
                    else 
                    {
                        builder.Append(type.FullName); 
                    }
                }

                builder.Append(')'); 
            }
 
            return builder.ToString(); 
        }
 
        /// Creates and populates a dictionary of system functions.
        /// A new dictionary of functions.
        internal static Dictionary CreateFunctions()
        { 
            Dictionary result = new Dictionary(StringComparer.Ordinal);
 
            // String functions. 
            FunctionDescription[] signatures;
            result.Add("endswith", new FunctionDescription[] { StringInstanceFunction("EndsWith", typeof(string)) }); 
            result.Add("indexof", new FunctionDescription[] { StringInstanceFunction("IndexOf", typeof(string)) });
            result.Add("replace", new FunctionDescription[] { StringInstanceFunction("Replace", typeof(string), typeof(string)) });
            result.Add("startswith", new FunctionDescription[] { StringInstanceFunction("StartsWith", typeof(string)) });
            result.Add("tolower", new FunctionDescription[] { StringInstanceFunction("ToLower", Type.EmptyTypes) }); 
            result.Add("toupper", new FunctionDescription[] { StringInstanceFunction("ToUpper", Type.EmptyTypes) });
            result.Add("trim", new FunctionDescription[] { StringInstanceFunction("Trim", Type.EmptyTypes) }); 
 
            signatures = new FunctionDescription[]
            { 
                StringInstanceFunction("Substring", typeof(int)),
                StringInstanceFunction("Substring", typeof(int), typeof(int))
            };
            result.Add("substring", signatures); 

            signatures = new FunctionDescription[] 
            { 
                new FunctionDescription("substringof", new Type[] { typeof(string), typeof(string) }, SubstringOf)
            }; 
            result.Add("substringof", signatures);

            signatures = new FunctionDescription[]
            { 
                CreateFunctionDescription(typeof(string), false /* instance */, true /* method */, "Concat", typeof(string), typeof(string))
            }; 
            result.Add("concat", signatures); 

            signatures = new FunctionDescription[] 
            {
                CreateFunctionDescription(typeof(string), true /* instance */, false /* method */, "Length", Type.EmptyTypes)
            };
            result.Add("length", signatures); 

            // DateTime functions. 
            result.Add("year", DateTimeFunctionArray("Year")); 
            result.Add("month", DateTimeFunctionArray("Month"));
            result.Add("day", DateTimeFunctionArray("Day")); 
            result.Add("hour", DateTimeFunctionArray("Hour"));
            result.Add("minute", DateTimeFunctionArray("Minute"));
            result.Add("second", DateTimeFunctionArray("Second"));
 
            // Mathematical functions.
            result.Add("round", MathFunctionArray("Round")); 
            result.Add("floor", MathFunctionArray("Floor")); 
            result.Add("ceiling", MathFunctionArray("Ceiling"));
 
            // Type functions.
            signatures = new FunctionDescription[]
            {
                new FunctionDescription(FunctionNameIsOf, new Type[] { typeof(Type) }, new Func(FunctionDescription.UnaryIsOf)), 
                new FunctionDescription(FunctionNameIsOf, new Type[] { typeof(object), typeof(Type) }, new Func(FunctionDescription.BinaryIsOf)),
            }; 
            result.Add(FunctionNameIsOf, signatures); 

            // For cast() signatures, we need to add all primitive types directly as well as the object (open type) 
            // and unary versions; otherwise expression will convert to object, then again to whatever other type
            // is required.
            System.Data.Services.Providers.ResourceType[] primitiveTypes = WebUtil.GetPrimitiveTypes();
            List castSignatures = new List(2 + primitiveTypes.Length * 2); 
            for (int i = 0; i < primitiveTypes.Length; i++)
            { 
                Debug.Assert( 
                    primitiveTypes[i].Type != typeof(Type),
                    "primitiveTypes[i].Type != typeof(Type) -- otherwise extra signatures will be added for cast()"); 
                Debug.Assert(
                    primitiveTypes[i].Type != typeof(object),
                    "primitiveTypes[i].Type != typeof(object) -- otherwise extra signatures will be added for cast()");
                castSignatures.Add(new FunctionDescription( 
                    FunctionNameCast,
                    new Type[] { primitiveTypes[i].Type, typeof(Type) }, 
                    new Func(FunctionDescription.BinaryCast))); 
                if (primitiveTypes[i].Type.IsValueType)
                { 
                    castSignatures.Add(new FunctionDescription(
                        FunctionNameCast,
                        new Type[] { typeof(Nullable<>).MakeGenericType(primitiveTypes[i].Type), typeof(Type) },
                        new Func(FunctionDescription.BinaryCast))); 
                }
            } 
 
            castSignatures.Add(
                new FunctionDescription(FunctionNameCast, new Type[] { typeof(Type) }, FunctionDescription.UnaryCast)); 
            castSignatures.Add(
                new FunctionDescription(FunctionNameCast, new Type[] { typeof(object), typeof(Type) }, new Func(FunctionDescription.BinaryCast)));

            result.Add(FunctionNameCast, castSignatures.ToArray()); 

            return result; 
        } 

        /// Transforms a URI-style "substringof(a,b)" function into "a.contains(b)". 
        /// Target of query; not used.
        /// Arguments to function.
        /// The conversion for this method.
        internal static Expression SubstringOf(Expression target, Expression[] arguments) 
        {
            Debug.Assert(arguments != null, "arguments != null"); 
            Debug.Assert(arguments.Length == 2, "arguments.Length == 2"); 

            BindingFlags flags = BindingFlags.Public | BindingFlags.Instance; 
            Type[] parameterTypes = new Type[] { typeof(string) };
            MethodInfo method = typeof(string).GetMethod("Contains", flags, null, parameterTypes, null);
            Debug.Assert(method != null, "method != null -- otherwise couldn't find string.Contains(string)");
            return Expression.Call(arguments[1], method, arguments[0]); 
        }
 
        /// Performs a type check for the "it" expression. 
        /// "it" expression.
        /// Argument for type check; type. 
        /// A new expression with the type check.
        internal static Expression UnaryIsOf(Expression target, Expression[] arguments)
        {
            ConstantExpression ce = (ConstantExpression)arguments[0]; 
            return Expression.TypeIs(target, (Type)ce.Value);
        } 
 
        /// Performs a type check for a given expression.
        /// "it" expression; unused by this function. 
        /// Arguments for type check; instance and type.
        /// A new expression with the type check.
        internal static Expression BinaryIsOf(Expression target, Expression[] arguments)
        { 
            ConstantExpression ce = (ConstantExpression)arguments[1];
            return Expression.TypeIs(arguments[0], (Type)ce.Value); 
        } 

        /// Performs a cast for the "it" expression. 
        /// "it" expression.
        /// Argument for cast; type.
        /// A new expression with the cast.
        internal static Expression UnaryCast(Expression target, Expression[] arguments) 
        {
            Debug.Assert(arguments.Length == 1, "arguments.Length == 1"); 
            ConstantExpression ce = (ConstantExpression)arguments[0]; 
            return Expression.Convert(target, (Type)ce.Value);
        } 

        /// Performs a cast for a given expression.
        /// "it" expression; unused by this function.
        /// Arguments for cast; instance and type. 
        /// A new expression with the cast.
        internal static Expression BinaryCast(Expression target, Expression[] arguments) 
        { 
            Debug.Assert(arguments.Length == 2, "arguments.Length == 2");
            ConstantExpression ce = (ConstantExpression)arguments[1]; 

            // Work around for SQLBUDT #615702 - Protocol: exception thrown in XML with filter=null
            //
            // We need this in place so we can recognize null constant reliably and generate 
            // trees that work for both LINQ to Entities and LINQ to Objects for the cases where
            // conversions of null literals generate expressions that don't guard for nulls in the 
            // EF case, but EF ends up calling them anyway because they can be evaluated on the client. 
            Type targetType = (Type)ce.Value;
            if (RequestQueryParser.IsNullConstant(arguments[0])) 
            {
                targetType = RequestQueryParser.GetTypeAllowingNull(targetType);
                return Expression.Constant(null, targetType);
            } 

            return Expression.Convert(arguments[0], targetType); 
        } 

        /// Creates a new function description for a method or property. 
        /// Type on which property or method is declared.
        /// Whether an instance member is looked for.
        /// Whether a method (rather than a property) is looked for.
        /// Name of member. 
        /// Parameter types.
        /// A new function description. 
        private static FunctionDescription CreateFunctionDescription( 
            Type targetType,
            bool instance, 
            bool method,
            string name,
            params Type[] parameterTypes)
        { 
            Debug.Assert(targetType != null, "targetType != null");
            Debug.Assert(name != null, "name != null"); 
            Debug.Assert(parameterTypes.Length == 0 || method, "parameterTypes.Length == 0 || method"); 
            Debug.Assert(method || instance, "method || instance");
 
            BindingFlags flags = BindingFlags.Public | (instance ? BindingFlags.Instance : BindingFlags.Static);
            MemberInfo member;

            if (method) 
            {
                member = targetType.GetMethod(name, flags, null, parameterTypes, null); 
                Debug.Assert(member != null, "methodInfo != null"); 
            }
            else 
            {
                member = targetType.GetProperty(name, flags);
                Debug.Assert(member != null, "propertyInfo != null");
            } 

            Type[] functionParameterTypes; 
            if (instance) 
            {
                functionParameterTypes = new Type[parameterTypes.Length + 1]; 
                functionParameterTypes[0] = targetType;
                parameterTypes.CopyTo(functionParameterTypes, 1);
            }
            else 
            {
                functionParameterTypes = parameterTypes; 
            } 

            FunctionDescription result = new FunctionDescription(member, functionParameterTypes); 
            if (method)
            {
                if (instance)
                { 
                    result.ConversionFunction = new Func(result.InstanceMethodConvertionFunction);
                } 
                else 
                {
                    result.ConversionFunction = new Func(result.StaticMethodConvertionFunction); 
                }
            }
            else
            { 
                Debug.Assert(instance, "instance");
                result.ConversionFunction = new Func(result.InstancePropertyConvertionFunction); 
            } 

            return result; 
        }

        /// Creates a description for a string instance method.
        /// Name of method to look up. 
        /// Parameter types to match.
        /// A new function description. 
        private static FunctionDescription StringInstanceFunction(string name, params Type[] parameterTypes) 
        {
            return CreateFunctionDescription(typeof(string), true /* instance */, true /* method */, name, parameterTypes); 
        }

        /// Creates an array of function description for a DateTime property.
        /// Name of property to look up. 
        /// A new function description array.
        private static FunctionDescription[] DateTimeFunctionArray(string name) 
        { 
            return new FunctionDescription[]
            { 
                CreateFunctionDescription(typeof(DateTime), true /* instance */, false /* method */, name, Type.EmptyTypes)
            };
        }
 
        /// Creates an array of function description for math method with decimal and double overloads.
        /// Name of method to look up. 
        /// A new function description array. 
        private static FunctionDescription[] MathFunctionArray(string name)
        { 
            return new FunctionDescription[]
            {
                CreateFunctionDescription(typeof(Math), false /* instance */, true /* method */, name, typeof(double)),
                CreateFunctionDescription(typeof(Math), false /* instance */, true /* method */, name, typeof(decimal)), 
            };
        } 
    } 
}

// 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