Code:
/ 4.0 / 4.0 / untmp / 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 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 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, 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) }, 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
- ByteFacetDescriptionElement.cs
- MimeReflector.cs
- AssemblyUtil.cs
- MatrixTransform.cs
- DetailsViewPageEventArgs.cs
- IndexOutOfRangeException.cs
- PropertyDescriptorGridEntry.cs
- HttpRuntimeSection.cs
- HttpContextWrapper.cs
- XmlTextReaderImplHelpers.cs
- WebEvents.cs
- CookieProtection.cs
- VSWCFServiceContractGenerator.cs
- WizardPanelChangingEventArgs.cs
- FactoryGenerator.cs
- UIAgentCrashedException.cs
- DialogResultConverter.cs
- CodeTypeMemberCollection.cs
- TextBoxBase.cs
- SystemWebSectionGroup.cs
- GPRECT.cs
- XmlKeywords.cs
- JavaScriptSerializer.cs
- Rect.cs
- XPathException.cs
- _PooledStream.cs
- UnsafeNativeMethods.cs
- ToolStripPanelRow.cs
- EntityDataSource.cs
- HttpDateParse.cs
- XmlReaderDelegator.cs
- NTAccount.cs
- InputElement.cs
- ObjectDataSourceStatusEventArgs.cs
- DefaultMemberAttribute.cs
- WpfGeneratedKnownProperties.cs
- SingleAnimationBase.cs
- TTSEngineTypes.cs
- XPathMessageFilterElementCollection.cs
- ThicknessConverter.cs
- BindToObject.cs
- Int64Storage.cs
- FixUpCollection.cs
- WindowsFormsLinkLabel.cs
- Vector3DCollectionValueSerializer.cs
- ProviderBase.cs
- autovalidator.cs
- UdpDuplexChannel.cs
- ImageCodecInfo.cs
- SecurityTokenReferenceStyle.cs
- InvalidCastException.cs
- XmlDocumentSerializer.cs
- XmlCharType.cs
- CompiledELinqQueryState.cs
- TypefaceMetricsCache.cs
- ArrayList.cs
- BaseAppDomainProtocolHandler.cs
- ResXResourceWriter.cs
- SubpageParaClient.cs
- xml.cs
- StyleCollection.cs
- StickyNote.cs
- WorkItem.cs
- JournalNavigationScope.cs
- altserialization.cs
- JavascriptCallbackResponseProperty.cs
- AutomationTextAttribute.cs
- CurrentChangingEventArgs.cs
- PageCanvasSize.cs
- _LoggingObject.cs
- UIHelper.cs
- TextBox.cs
- ResourceDictionaryCollection.cs
- PointCollectionConverter.cs
- HtmlInputRadioButton.cs
- TabControlAutomationPeer.cs
- ListViewUpdateEventArgs.cs
- ActivityPropertyReference.cs
- BuildResultCache.cs
- TextClipboardData.cs
- ShapingEngine.cs
- InvalidOperationException.cs
- HwndProxyElementProvider.cs
- SyntaxCheck.cs
- WebControlsSection.cs
- SymmetricAlgorithm.cs
- DataServiceKeyAttribute.cs
- ServiceThrottlingElement.cs
- DisableDpiAwarenessAttribute.cs
- GridViewUpdatedEventArgs.cs
- Attributes.cs
- RotateTransform.cs
- SqlNotificationEventArgs.cs
- IisTraceWebEventProvider.cs
- FileLevelControlBuilderAttribute.cs
- UrlAuthorizationModule.cs
- ScopelessEnumAttribute.cs
- CultureInfoConverter.cs
- ArrayTypeMismatchException.cs
- safelinkcollection.cs