Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / Core / Microsoft / Scripting / Ast / IndexExpression.cs / 1305376 / IndexExpression.cs
/* **************************************************************************** * * Copyright (c) Microsoft Corporation. * * This source code is subject to terms and conditions of the Microsoft Public License. A * copy of the license can be found in the License.html file at the root of this distribution. If * you cannot locate the Microsoft Public License, please send an email to * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound * by the terms of the Microsoft Public License. * * You must not remove this notice, or any other, from this software. * * * ***************************************************************************/ using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; using System.Dynamic.Utils; using System.Reflection; using System.Runtime.CompilerServices; using System.Text; #if SILVERLIGHT using System.Core; #endif namespace System.Linq.Expressions { ////// Represents indexing a property or array. /// #if !SILVERLIGHT [DebuggerTypeProxy(typeof(Expression.IndexExpressionProxy))] #endif public sealed class IndexExpression : Expression, IArgumentProvider { private readonly Expression _instance; private readonly PropertyInfo _indexer; private IList_arguments; internal IndexExpression( Expression instance, PropertyInfo indexer, IList arguments) { if (indexer == null) { Debug.Assert(instance != null && instance.Type.IsArray); Debug.Assert(instance.Type.GetArrayRank() == arguments.Count); } _instance = instance; _indexer = indexer; _arguments = arguments; } /// /// Returns the node type of this ///. (Inherited from .) /// The public sealed override ExpressionType NodeType { get { return ExpressionType.Index; } } ///that represents this expression. /// Gets the static type of the expression that this ///represents. (Inherited from .) /// The public sealed override Type Type { get { if (_indexer != null) { return _indexer.PropertyType; } return _instance.Type.GetElementType(); } } ///that represents the static type of the expression. /// An object to index. /// public Expression Object { get { return _instance; } } ////// Gets the public PropertyInfo Indexer { get { return _indexer; } } ///for the property if the expression represents an indexed property, returns null otherwise. /// /// Gets the arguments to be used to index the property or array. /// public ReadOnlyCollectionArguments { get { return ReturnReadOnly(ref _arguments); } } /// /// Creates a new expression that is like this one, but using the /// supplied children. If all of the children are the same, it will /// return this expression. /// /// Theproperty of the result. /// The property of the result. /// This expression if no children changed, or an expression with the updated children. public IndexExpression Update(Expression @object, IEnumerablearguments) { if (@object == Object && arguments == Arguments) { return this; } return Expression.MakeIndex(@object, Indexer, arguments); } Expression IArgumentProvider.GetArgument(int index) { return _arguments[index]; } int IArgumentProvider.ArgumentCount { get { return _arguments.Count; } } /// /// Dispatches to the specific visit method for this node type. /// protected internal override Expression Accept(ExpressionVisitor visitor) { return visitor.VisitIndex(this); } internal Expression Rewrite(Expression instance, Expression[] arguments) { Debug.Assert(instance != null); Debug.Assert(arguments == null || arguments.Length == _arguments.Count); return Expression.MakeIndex(instance, _indexer, arguments ?? _arguments); } } public partial class Expression { ////// Creates an /// The object to which the property belongs. Should be null if the property is static(shared). /// Anthat represents accessing an indexed property in an object. /// representing the property to index. /// An IEnumerable{Expression} contaning the arguments to be used to index the property. /// The created public static IndexExpression MakeIndex(Expression instance, PropertyInfo indexer, IEnumerable. arguments) { if (indexer != null) { return Property(instance, indexer, arguments); } else { return ArrayAccess(instance, arguments); } } #region ArrayAccess /// /// Creates an /// An expression representing the array to index. /// An array containing expressions used to index the array. ///to access an array. /// The expression representing the array can be obtained by using the MakeMemberAccess method, /// or through NewArrayBounds or NewArrayInit. ///The created public static IndexExpression ArrayAccess(Expression array, params Expression[] indexes) { return ArrayAccess(array, (IEnumerable. )indexes); } /// /// Creates an /// An expression representing the array to index. /// Anto access an array. /// containing expressions used to index the array. /// The expression representing the array can be obtained by using the MakeMemberAccess method, /// or through NewArrayBounds or NewArrayInit. ///The created public static IndexExpression ArrayAccess(Expression array, IEnumerable. indexes) { RequiresCanRead(array, "array"); Type arrayType = array.Type; if (!arrayType.IsArray) { throw Error.ArgumentMustBeArray(); } var indexList = indexes.ToReadOnly(); if (arrayType.GetArrayRank() != indexList.Count) { throw Error.IncorrectNumberOfIndexes(); } foreach (Expression e in indexList) { RequiresCanRead(e, "indexes"); if (e.Type != typeof(int)) { throw Error.ArgumentMustBeArrayIndexType(); } } return new IndexExpression(array, null, indexList); } #endregion #region Property /// /// Creates an /// The object to which the property belongs. If the property is static/shared, it must be null. /// The name of the indexer. /// An array ofrepresenting the access to an indexed property. /// objects that are used to index the property. /// The created public static IndexExpression Property(Expression instance, string propertyName, params Expression[] arguments) { RequiresCanRead(instance, "instance"); ContractUtils.RequiresNotNull(propertyName, "indexerName"); PropertyInfo pi = FindInstanceProperty(instance.Type, propertyName, arguments); return Property(instance, pi, arguments); } #region methods for finding a PropertyInfo by its name ///. /// The method finds the instance property with the specified name in a type. The property's type signature needs to be compatible with /// the arguments if it is a indexer. If the arguments is null or empty, we get a normal property. /// private static PropertyInfo FindInstanceProperty(Type type, string propertyName, Expression[] arguments) { // bind to public names first BindingFlags flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.IgnoreCase | BindingFlags.FlattenHierarchy; PropertyInfo pi = FindProperty(type, propertyName, arguments, flags); if (pi == null) { flags = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.IgnoreCase | BindingFlags.FlattenHierarchy; pi = FindProperty(type, propertyName, arguments, flags); } if (pi == null) { if (arguments == null || arguments.Length == 0) { throw Error.InstancePropertyWithoutParameterNotDefinedForType(propertyName, type); } else { throw Error.InstancePropertyWithSpecifiedParametersNotDefinedForType(propertyName, GetArgTypesString(arguments), type); } } return pi; } private static string GetArgTypesString(Expression[] arguments) { StringBuilder argTypesStr = new StringBuilder(); var isFirst = true; argTypesStr.Append("("); foreach (var t in arguments.Select(arg => arg.Type)) { if (!isFirst) { argTypesStr.Append(", "); } argTypesStr.Append(t.Name); isFirst = false; } argTypesStr.Append(")"); return argTypesStr.ToString(); } private static PropertyInfo FindProperty(Type type, string propertyName, Expression[] arguments, BindingFlags flags) { MemberInfo[] members = type.FindMembers(MemberTypes.Property, flags, Type.FilterNameIgnoreCase, propertyName); if (members == null || members.Length == 0) return null; PropertyInfo pi; var propertyInfos = members.Map(t => (PropertyInfo)t); int count = FindBestProperty(propertyInfos, arguments, out pi); if (count == 0) return null; if (count > 1) throw Error.PropertyWithMoreThanOneMatch(propertyName, type); return pi; } private static int FindBestProperty(IEnumerableproperties, Expression[] args, out PropertyInfo property) { int count = 0; property = null; foreach (PropertyInfo pi in properties) { if (pi != null && IsCompatible(pi, args)) { if (property == null) { property = pi; count = 1; } else { count++; } } } return count; } private static bool IsCompatible(PropertyInfo pi, Expression[] args) { MethodInfo mi; mi = pi.GetGetMethod(true); ParameterInfo[] parms; if (mi != null) { parms = mi.GetParametersCached(); } else { mi = pi.GetSetMethod(true); //The setter has an additional parameter for the value to set, //need to remove the last type to match the arguments. parms = mi.GetParametersCached().RemoveLast(); } if (mi == null) { return false; } if (args == null) { return parms.Length == 0; } if (parms.Length != args.Length) return false; for (int i = 0; i < args.Length; i++) { if (args[i] == null) return false; if (!TypeUtils.AreReferenceAssignable(parms[i].ParameterType, args[i].Type)) { return false; } } return true; } #endregion /// /// Creates an /// The object to which the property belongs. If the property is static/shared, it must be null. /// Therepresenting the access to an indexed property. /// that represents the property to index. /// An array of objects that are used to index the property. /// The created public static IndexExpression Property(Expression instance, PropertyInfo indexer, params Expression[] arguments) { return Property(instance, indexer, (IEnumerable. )arguments); } /// /// Creates an /// The object to which the property belongs. If the property is static/shared, it must be null. /// Therepresenting the access to an indexed property. /// that represents the property to index. /// An of objects that are used to index the property. /// The created public static IndexExpression Property(Expression instance, PropertyInfo indexer, IEnumerable. arguments) { var argList = arguments.ToReadOnly(); ValidateIndexedProperty(instance, indexer, ref argList); return new IndexExpression(instance, indexer, argList); } // CTS places no restrictions on properties (see ECMA-335 8.11.3), // so we validate that the property conforms to CLS rules here. // // Does reflection help us out at all? Expression.Property skips all of // these checks, so either it needs more checks or we need less here. private static void ValidateIndexedProperty(Expression instance, PropertyInfo property, ref ReadOnlyCollection argList) { // If both getter and setter specified, all their parameter types // should match, with exception of the last setter parameter which // should match the type returned by the get method. // Accessor parameters cannot be ByRef. ContractUtils.RequiresNotNull(property, "property"); if (property.PropertyType.IsByRef) throw Error.PropertyCannotHaveRefType(); if (property.PropertyType == typeof(void)) throw Error.PropertyTypeCannotBeVoid(); ParameterInfo[] getParameters = null; MethodInfo getter = property.GetGetMethod(true); if (getter != null) { getParameters = getter.GetParametersCached(); ValidateAccessor(instance, getter, getParameters, ref argList); } MethodInfo setter = property.GetSetMethod(true); if (setter != null) { ParameterInfo[] setParameters = setter.GetParametersCached(); if (setParameters.Length == 0) throw Error.SetterHasNoParams(); // valueType is the type of the value passed to the setter (last parameter) Type valueType = setParameters[setParameters.Length - 1].ParameterType; if (valueType.IsByRef) throw Error.PropertyCannotHaveRefType(); if (setter.ReturnType != typeof(void)) throw Error.SetterMustBeVoid(); if (property.PropertyType != valueType) throw Error.PropertyTyepMustMatchSetter(); if (getter != null) { if (getter.IsStatic ^ setter.IsStatic) throw Error.BothAccessorsMustBeStatic(); if (getParameters.Length != setParameters.Length - 1) throw Error.IndexesOfSetGetMustMatch(); for (int i = 0; i < getParameters.Length; i++) { if (getParameters[i].ParameterType != setParameters[i].ParameterType) throw Error.IndexesOfSetGetMustMatch(); } } else { ValidateAccessor(instance, setter, setParameters.RemoveLast(), ref argList); } } if (getter == null && setter == null) { throw Error.PropertyDoesNotHaveAccessor(property); } } private static void ValidateAccessor(Expression instance, MethodInfo method, ParameterInfo[] indexes, ref ReadOnlyCollection arguments) { ContractUtils.RequiresNotNull(arguments, "arguments"); ValidateMethodInfo(method); if ((method.CallingConvention & CallingConventions.VarArgs) != 0) throw Error.AccessorsCannotHaveVarArgs(); if (method.IsStatic) { if (instance != null) throw Error.OnlyStaticMethodsHaveNullInstance(); } else { if (instance == null) throw Error.OnlyStaticMethodsHaveNullInstance(); RequiresCanRead(instance, "instance"); ValidateCallInstanceType(instance.Type, method); } ValidateAccessorArgumentTypes(method, indexes, ref arguments); } private static void ValidateAccessorArgumentTypes(MethodInfo method, ParameterInfo[] indexes, ref ReadOnlyCollection arguments) { if (indexes.Length > 0) { if (indexes.Length != arguments.Count) { throw Error.IncorrectNumberOfMethodCallArguments(method); } Expression[] newArgs = null; for (int i = 0, n = indexes.Length; i < n; i++) { Expression arg = arguments[i]; ParameterInfo pi = indexes[i]; RequiresCanRead(arg, "arguments"); Type pType = pi.ParameterType; if (pType.IsByRef) throw Error.AccessorsCannotHaveByRefArgs(); TypeUtils.ValidateType(pType); if (!TypeUtils.AreReferenceAssignable(pType, arg.Type)) { if (TypeUtils.IsSameOrSubclass(typeof(LambdaExpression), pType) && pType.IsAssignableFrom(arg.GetType())) { arg = Expression.Quote(arg); } else { throw Error.ExpressionTypeDoesNotMatchMethodParameter(arg.Type, pType, method); } } if (newArgs == null && arg != arguments[i]) { newArgs = new Expression[arguments.Count]; for (int j = 0; j < i; j++) { newArgs[j] = arguments[j]; } } if (newArgs != null) { newArgs[i] = arg; } } if (newArgs != null) { arguments = new TrueReadOnlyCollection (newArgs); } } else if (arguments.Count > 0) { throw Error.IncorrectNumberOfMethodCallArguments(method); } } #endregion } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- BitmapImage.cs
- DBSchemaRow.cs
- Exceptions.cs
- ProfileGroupSettings.cs
- PaperSource.cs
- SequentialUshortCollection.cs
- OdbcException.cs
- EntityClientCacheKey.cs
- Accessors.cs
- XmlSortKey.cs
- BasicViewGenerator.cs
- EntityUtil.cs
- QueryExpr.cs
- Attachment.cs
- ExtentCqlBlock.cs
- CryptoApi.cs
- KeysConverter.cs
- DataTemplate.cs
- XPathNodeInfoAtom.cs
- BrowserDefinition.cs
- CultureInfo.cs
- Descriptor.cs
- ScriptRegistrationManager.cs
- SQLInt16.cs
- FormViewDeleteEventArgs.cs
- ClientConfigurationSystem.cs
- OracleCommandSet.cs
- DataPointer.cs
- InfiniteIntConverter.cs
- SimpleType.cs
- StreamInfo.cs
- CompressionTransform.cs
- QuaternionIndependentAnimationStorage.cs
- DescendentsWalkerBase.cs
- XmlCharCheckingReader.cs
- GeneralTransform2DTo3D.cs
- RuntimeConfig.cs
- WindowsListView.cs
- TreeNodeSelectionProcessor.cs
- CmsInterop.cs
- PenLineCapValidation.cs
- ConcurrentStack.cs
- StringWriter.cs
- ResourceProviderFactory.cs
- BitmapCacheBrush.cs
- AppDomainFactory.cs
- GlyphingCache.cs
- EntityTypeBase.cs
- AppSecurityManager.cs
- DynamicResourceExtension.cs
- X500Name.cs
- FileLoadException.cs
- FrameworkTemplate.cs
- SegmentInfo.cs
- WSDualHttpBindingElement.cs
- ConfigurationManagerInternal.cs
- SecurityRuntime.cs
- SQLSingle.cs
- ClickablePoint.cs
- ApplicationDirectoryMembershipCondition.cs
- Vector3DCollection.cs
- WindowsTokenRoleProvider.cs
- BinaryObjectWriter.cs
- ScrollChrome.cs
- XmlSchemaParticle.cs
- WindowsHyperlink.cs
- DateTimeAutomationPeer.cs
- DbDataAdapter.cs
- HttpResponse.cs
- ForEachAction.cs
- SchemaComplexType.cs
- FreeFormDesigner.cs
- SafeArchiveContext.cs
- DelayDesigner.cs
- RangeValuePattern.cs
- Helper.cs
- ReflectTypeDescriptionProvider.cs
- GCHandleCookieTable.cs
- DesignerWebPartChrome.cs
- RequestSecurityTokenForGetBrowserToken.cs
- EmissiveMaterial.cs
- Main.cs
- TextRunTypographyProperties.cs
- ServiceDescriptionContext.cs
- TargetParameterCountException.cs
- DataObjectCopyingEventArgs.cs
- TrustLevel.cs
- MethodAccessException.cs
- InputMethodStateTypeInfo.cs
- CounterSample.cs
- EmbossBitmapEffect.cs
- PolyLineSegment.cs
- EditingMode.cs
- XmlNodeChangedEventArgs.cs
- SqlFacetAttribute.cs
- smtppermission.cs
- RayMeshGeometry3DHitTestResult.cs
- PackageFilter.cs
- StylusPlugInCollection.cs
- BinaryMethodMessage.cs