Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / DataWeb / Server / System / Data / Services / Parsing / FunctionDescription.cs / 1305376 / 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; using System.Data.Services.Providers; ///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 FuncconversionFunction; /// 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 FuncConversionFunction { [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 InstanceMethodConversionFunction(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 StaticMethodConversionFunction(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 InstancePropertyConversionFunction(Expression target, Expression[] arguments) { return Expression.Property(arguments[0], (PropertyInfo)this.member); } ////// Invoke the open typed method for this function. /// /// list of parameters to pass to the late bound method. ///A new expression with the late bound function public Expression InvokeOpenTypeMethod(Expression[] arguments) { Debug.Assert(arguments != null, "arguments != null"); Debug.Assert(arguments.Length == this.ParameterTypes.Length, "arguments.Length == this.ParameterTypes.Length"); Type[] argumentTypes = new Type[this.parameterTypes.Length]; for (int i = 0; i < argumentTypes.Length; i++) { argumentTypes[i] = typeof(object); } MethodInfo methodInfo = typeof(OpenTypeMethods).GetMethod( this.name, BindingFlags.Static | BindingFlags.Public, null, argumentTypes, null); Debug.Assert(methodInfo != null, "methodInfo != null"); return Expression.Call(null, methodInfo, arguments); } ///Builds a list of function signatures. /// Function name. /// Function descriptions. ///A string with ';'-separated list of function signatures. internal static string BuildSignatureList(string name, IEnumerabledescriptions) { 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 DictionaryCreateFunctions() { 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) }, FunctionDescription.UnaryIsOf), new FunctionDescription(FunctionNameIsOf, new Type[] { typeof(object), typeof(Type) }, FunctionDescription.BinaryIsOf), new FunctionDescription(FunctionNameIsOf, new Type[] { typeof(ResourceType) }, FunctionDescription.UnaryIsOfResourceType), new FunctionDescription(FunctionNameIsOf, new Type[] { typeof(object), typeof(ResourceType) }, FunctionDescription.BinaryIsOfResourceType), }; 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 (primitiveTypes.Length + 4); for (int i = 0; i < primitiveTypes.Length; i++) { Debug.Assert( primitiveTypes[i].InstanceType != typeof(Type), "primitiveTypes[i].Type != typeof(Type) -- otherwise extra signatures will be added for cast()"); Debug.Assert( primitiveTypes[i].InstanceType != typeof(object), "primitiveTypes[i].Type != typeof(object) -- otherwise extra signatures will be added for cast()"); castSignatures.Add(new FunctionDescription(FunctionNameCast, new Type[] { primitiveTypes[i].InstanceType, typeof(Type) }, FunctionDescription.BinaryCast)); } castSignatures.Add(new FunctionDescription(FunctionNameCast, new Type[] { typeof(Type) }, FunctionDescription.UnaryCast)); castSignatures.Add(new FunctionDescription(FunctionNameCast, new Type[] { typeof(object), typeof(Type) }, FunctionDescription.BinaryCast)); castSignatures.Add(new FunctionDescription(FunctionNameCast, new Type[] { typeof(ResourceType) }, FunctionDescription.UnaryCastResourceType)); castSignatures.Add(new FunctionDescription(FunctionNameCast, new Type[] { typeof(object), typeof(ResourceType) }, FunctionDescription.BinaryCastResourceType)); 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 type check for the "it" expression. /// "it" expression. /// Argument for type check; type. ///A new expression with the type check. internal static Expression UnaryIsOfResourceType(Expression target, Expression[] arguments) { Debug.Assert(arguments != null, "arguments != null"); Debug.Assert(arguments.Length == 1, "arguments.Length == 1"); Debug.Assert(arguments[0].NodeType == ExpressionType.Constant, "Constant expression expected for argument[0]"); Debug.Assert(((ConstantExpression)arguments[0]).Type == typeof(ResourceType), "Constant expression type should be ResourceType"); return Expression.Call(null, DataServiceProviderMethods.TypeIsMethodInfo, target, arguments[0]); } ///Performs a type check for a given expression. /// "it" expression; unused by this function. /// Arguments for type check; instance and resource type. ///A new expression with the type check. internal static Expression BinaryIsOfResourceType(Expression target, Expression[] arguments) { Debug.Assert(arguments != null, "arguments != null"); Debug.Assert(arguments.Length == 3, "arguments.Length == 3"); Debug.Assert(arguments[1].NodeType == ExpressionType.Constant, "Constant expression expected for argument[1]"); Debug.Assert(((ConstantExpression)arguments[1]).Type == typeof(ResourceType), "Constant expression type should be ResourceType"); Debug.Assert(arguments[2].NodeType == ExpressionType.Constant, "Constant expression expected for argument[2]"); Debug.Assert(((ConstantExpression)arguments[2]).Type == typeof(bool), "Constant expression type should be boolean"); bool callOpenTypeMethod = ((bool)((ConstantExpression)arguments[2]).Value) == true; return Expression.Call(null, callOpenTypeMethod ? OpenTypeMethods.TypeIsMethodInfo : DataServiceProviderMethods.TypeIsMethodInfo, arguments[0], arguments[1]); } ///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 (WebUtil.IsNullConstant(arguments[0])) { targetType = WebUtil.GetTypeAllowingNull(targetType); return Expression.Constant(null, targetType); } return Expression.Convert(arguments[0], targetType); } ///Performs a cast for the "it" expression. /// "it" expression. /// Argument for cast; type. ///A new expression with the cast. internal static Expression UnaryCastResourceType(Expression target, Expression[] arguments) { Debug.Assert(arguments != null, "arguments != null"); Debug.Assert(arguments.Length == 1, "arguments.Length == 1"); Debug.Assert(arguments[0].NodeType == ExpressionType.Constant, "Constant expression expected for argument[0]"); Debug.Assert(((ConstantExpression)arguments[0]).Type == typeof(ResourceType), "Constant expression type should be ResourceType"); return Expression.Call(null, DataServiceProviderMethods.ConvertMethodInfo, target, arguments[0]); } ///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 BinaryCastResourceType(Expression target, Expression[] arguments) { Debug.Assert(arguments != null, "arguments != null"); Debug.Assert(arguments.Length == 3, "arguments.Length == 3"); Debug.Assert(arguments[1].NodeType == ExpressionType.Constant, "Constant expression expected for argument[1]"); Debug.Assert(((ConstantExpression)arguments[1]).Type == typeof(ResourceType), "Constant expression type should be ResourceType"); Debug.Assert(arguments[2].NodeType == ExpressionType.Constant, "Constant expression expected for argument[2]"); Debug.Assert(((ConstantExpression)arguments[2]).Type == typeof(bool), "Constant expression type should be boolean"); bool callOpenTypeMethod = ((bool)((ConstantExpression)arguments[2]).Value) == true; return Expression.Call(null, callOpenTypeMethod ? OpenTypeMethods.ConvertMethodInfo : DataServiceProviderMethods.ConvertMethodInfo, arguments[0], arguments[1]); } ///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.InstanceMethodConversionFunction); } else { result.ConversionFunction = new Func (result.StaticMethodConversionFunction); } } else { Debug.Assert(instance, "instance"); result.ConversionFunction = new Func (result.InstancePropertyConversionFunction); } 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; using System.Data.Services.Providers; ///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 FuncconversionFunction; /// 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 FuncConversionFunction { [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 InstanceMethodConversionFunction(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 StaticMethodConversionFunction(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 InstancePropertyConversionFunction(Expression target, Expression[] arguments) { return Expression.Property(arguments[0], (PropertyInfo)this.member); } ////// Invoke the open typed method for this function. /// /// list of parameters to pass to the late bound method. ///A new expression with the late bound function public Expression InvokeOpenTypeMethod(Expression[] arguments) { Debug.Assert(arguments != null, "arguments != null"); Debug.Assert(arguments.Length == this.ParameterTypes.Length, "arguments.Length == this.ParameterTypes.Length"); Type[] argumentTypes = new Type[this.parameterTypes.Length]; for (int i = 0; i < argumentTypes.Length; i++) { argumentTypes[i] = typeof(object); } MethodInfo methodInfo = typeof(OpenTypeMethods).GetMethod( this.name, BindingFlags.Static | BindingFlags.Public, null, argumentTypes, null); Debug.Assert(methodInfo != null, "methodInfo != null"); return Expression.Call(null, methodInfo, arguments); } ///Builds a list of function signatures. /// Function name. /// Function descriptions. ///A string with ';'-separated list of function signatures. internal static string BuildSignatureList(string name, IEnumerabledescriptions) { 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 DictionaryCreateFunctions() { 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) }, FunctionDescription.UnaryIsOf), new FunctionDescription(FunctionNameIsOf, new Type[] { typeof(object), typeof(Type) }, FunctionDescription.BinaryIsOf), new FunctionDescription(FunctionNameIsOf, new Type[] { typeof(ResourceType) }, FunctionDescription.UnaryIsOfResourceType), new FunctionDescription(FunctionNameIsOf, new Type[] { typeof(object), typeof(ResourceType) }, FunctionDescription.BinaryIsOfResourceType), }; 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 (primitiveTypes.Length + 4); for (int i = 0; i < primitiveTypes.Length; i++) { Debug.Assert( primitiveTypes[i].InstanceType != typeof(Type), "primitiveTypes[i].Type != typeof(Type) -- otherwise extra signatures will be added for cast()"); Debug.Assert( primitiveTypes[i].InstanceType != typeof(object), "primitiveTypes[i].Type != typeof(object) -- otherwise extra signatures will be added for cast()"); castSignatures.Add(new FunctionDescription(FunctionNameCast, new Type[] { primitiveTypes[i].InstanceType, typeof(Type) }, FunctionDescription.BinaryCast)); } castSignatures.Add(new FunctionDescription(FunctionNameCast, new Type[] { typeof(Type) }, FunctionDescription.UnaryCast)); castSignatures.Add(new FunctionDescription(FunctionNameCast, new Type[] { typeof(object), typeof(Type) }, FunctionDescription.BinaryCast)); castSignatures.Add(new FunctionDescription(FunctionNameCast, new Type[] { typeof(ResourceType) }, FunctionDescription.UnaryCastResourceType)); castSignatures.Add(new FunctionDescription(FunctionNameCast, new Type[] { typeof(object), typeof(ResourceType) }, FunctionDescription.BinaryCastResourceType)); 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 type check for the "it" expression. /// "it" expression. /// Argument for type check; type. ///A new expression with the type check. internal static Expression UnaryIsOfResourceType(Expression target, Expression[] arguments) { Debug.Assert(arguments != null, "arguments != null"); Debug.Assert(arguments.Length == 1, "arguments.Length == 1"); Debug.Assert(arguments[0].NodeType == ExpressionType.Constant, "Constant expression expected for argument[0]"); Debug.Assert(((ConstantExpression)arguments[0]).Type == typeof(ResourceType), "Constant expression type should be ResourceType"); return Expression.Call(null, DataServiceProviderMethods.TypeIsMethodInfo, target, arguments[0]); } ///Performs a type check for a given expression. /// "it" expression; unused by this function. /// Arguments for type check; instance and resource type. ///A new expression with the type check. internal static Expression BinaryIsOfResourceType(Expression target, Expression[] arguments) { Debug.Assert(arguments != null, "arguments != null"); Debug.Assert(arguments.Length == 3, "arguments.Length == 3"); Debug.Assert(arguments[1].NodeType == ExpressionType.Constant, "Constant expression expected for argument[1]"); Debug.Assert(((ConstantExpression)arguments[1]).Type == typeof(ResourceType), "Constant expression type should be ResourceType"); Debug.Assert(arguments[2].NodeType == ExpressionType.Constant, "Constant expression expected for argument[2]"); Debug.Assert(((ConstantExpression)arguments[2]).Type == typeof(bool), "Constant expression type should be boolean"); bool callOpenTypeMethod = ((bool)((ConstantExpression)arguments[2]).Value) == true; return Expression.Call(null, callOpenTypeMethod ? OpenTypeMethods.TypeIsMethodInfo : DataServiceProviderMethods.TypeIsMethodInfo, arguments[0], arguments[1]); } ///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 (WebUtil.IsNullConstant(arguments[0])) { targetType = WebUtil.GetTypeAllowingNull(targetType); return Expression.Constant(null, targetType); } return Expression.Convert(arguments[0], targetType); } ///Performs a cast for the "it" expression. /// "it" expression. /// Argument for cast; type. ///A new expression with the cast. internal static Expression UnaryCastResourceType(Expression target, Expression[] arguments) { Debug.Assert(arguments != null, "arguments != null"); Debug.Assert(arguments.Length == 1, "arguments.Length == 1"); Debug.Assert(arguments[0].NodeType == ExpressionType.Constant, "Constant expression expected for argument[0]"); Debug.Assert(((ConstantExpression)arguments[0]).Type == typeof(ResourceType), "Constant expression type should be ResourceType"); return Expression.Call(null, DataServiceProviderMethods.ConvertMethodInfo, target, arguments[0]); } ///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 BinaryCastResourceType(Expression target, Expression[] arguments) { Debug.Assert(arguments != null, "arguments != null"); Debug.Assert(arguments.Length == 3, "arguments.Length == 3"); Debug.Assert(arguments[1].NodeType == ExpressionType.Constant, "Constant expression expected for argument[1]"); Debug.Assert(((ConstantExpression)arguments[1]).Type == typeof(ResourceType), "Constant expression type should be ResourceType"); Debug.Assert(arguments[2].NodeType == ExpressionType.Constant, "Constant expression expected for argument[2]"); Debug.Assert(((ConstantExpression)arguments[2]).Type == typeof(bool), "Constant expression type should be boolean"); bool callOpenTypeMethod = ((bool)((ConstantExpression)arguments[2]).Value) == true; return Expression.Call(null, callOpenTypeMethod ? OpenTypeMethods.ConvertMethodInfo : DataServiceProviderMethods.ConvertMethodInfo, arguments[0], arguments[1]); } ///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.InstanceMethodConversionFunction); } else { result.ConversionFunction = new Func (result.StaticMethodConversionFunction); } } else { Debug.Assert(instance, "instance"); result.ConversionFunction = new Func (result.InstancePropertyConversionFunction); } 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
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- CroppedBitmap.cs
- GlobalProxySelection.cs
- TemplatedAdorner.cs
- ProjectionPlanCompiler.cs
- PrimitiveXmlSerializers.cs
- InternalRelationshipCollection.cs
- BitmapDecoder.cs
- BulletDecorator.cs
- KeyGestureValueSerializer.cs
- QueryResultOp.cs
- DataRelationPropertyDescriptor.cs
- Polygon.cs
- DefaultMemberAttribute.cs
- ExpressionBuilder.cs
- MissingSatelliteAssemblyException.cs
- CommonGetThemePartSize.cs
- ListDictionaryInternal.cs
- PackagePart.cs
- DbMetaDataFactory.cs
- XmlSchemaAnyAttribute.cs
- XmlSchemas.cs
- ResourceDictionary.cs
- FtpRequestCacheValidator.cs
- Rect3DConverter.cs
- TraceHwndHost.cs
- IsolatedStorageFilePermission.cs
- UrlPropertyAttribute.cs
- WrapPanel.cs
- WCFBuildProvider.cs
- RoutedUICommand.cs
- QilList.cs
- DCSafeHandle.cs
- FixedSOMTableCell.cs
- InternalTypeHelper.cs
- NavigationProperty.cs
- XPathParser.cs
- ResourceLoader.cs
- DataGridViewAutoSizeColumnsModeEventArgs.cs
- EntityContainer.cs
- ConcatQueryOperator.cs
- DataGridViewCellPaintingEventArgs.cs
- MsmqDiagnostics.cs
- ZoomPercentageConverter.cs
- path.cs
- XmlSchemaGroup.cs
- Source.cs
- Qualifier.cs
- Mouse.cs
- CLSCompliantAttribute.cs
- LinkDescriptor.cs
- ObjectDataSourceMethodEventArgs.cs
- ScrollEventArgs.cs
- ObjectSelectorEditor.cs
- DetailsViewActionList.cs
- URIFormatException.cs
- XmlRootAttribute.cs
- TileModeValidation.cs
- PreparingEnlistment.cs
- XmlILModule.cs
- PtsHost.cs
- ListViewTableCell.cs
- _ContextAwareResult.cs
- BaseDataListDesigner.cs
- versioninfo.cs
- SimpleBitVector32.cs
- DBCSCodePageEncoding.cs
- CodeChecksumPragma.cs
- SafeRightsManagementEnvironmentHandle.cs
- XmlSchemaComplexContentRestriction.cs
- LocationSectionRecord.cs
- ManifestBasedResourceGroveler.cs
- Input.cs
- QueryableFilterUserControl.cs
- HandlerFactoryWrapper.cs
- ServiceOperationParameter.cs
- ProcessManager.cs
- EntityContainerRelationshipSetEnd.cs
- XsdBuilder.cs
- CorrelationTokenInvalidatedHandler.cs
- SqlConnectionStringBuilder.cs
- IntegrationExceptionEventArgs.cs
- AtomEntry.cs
- ToolStripHighContrastRenderer.cs
- GlobalAllocSafeHandle.cs
- PixelShader.cs
- SelectionRangeConverter.cs
- WebPartsPersonalization.cs
- TypeUtils.cs
- XmlParser.cs
- InputBinding.cs
- PngBitmapEncoder.cs
- StyleHelper.cs
- Type.cs
- _SslSessionsCache.cs
- DatePickerTextBox.cs
- CodeThrowExceptionStatement.cs
- ExceptionHandlerDesigner.cs
- WorkflowInlining.cs
- HeaderedItemsControl.cs
- OutputScopeManager.cs