Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / Core / Microsoft / Scripting / Ast / Expression.cs / 1305376 / Expression.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.Dynamic.Utils; using System.Globalization; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Threading; #if SILVERLIGHT using System.Core; #endif namespace System.Linq.Expressions { ////// The base type for all nodes in Expression Trees. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1506:AvoidExcessiveClassCoupling")] public abstract partial class Expression { private delegate LambdaExpression LambdaFactory(Expression body, string name, bool tailCall, ReadOnlyCollectionparameters); private static readonly CacheDict _LambdaDelegateCache = new CacheDict (40); private static CacheDict _LambdaFactories; // LINQ protected ctor from 3.5 #if !MICROSOFT_SCRIPTING_CORE // needs ConditionWeakTable in 4.0 // For 4.0, many frequently used Expression nodes have had their memory // footprint reduced by removing the Type and NodeType fields. This has // large performance benefits to all users of Expression Trees. // // To support the 3.5 protected constructor, we store the fields that // used to be here in a ConditionalWeakTable. private class ExtensionInfo { public ExtensionInfo(ExpressionType nodeType, Type type) { NodeType = nodeType; Type = type; } internal readonly ExpressionType NodeType; internal readonly Type Type; } private static ConditionalWeakTable _legacyCtorSupportTable; /// /// Constructs a new instance of /// The. /// of the . /// The of the . [Obsolete("use a different constructor that does not take ExpressionType. Then override NodeType and Type properties to provide the values that would be specified to this constructor.")] protected Expression(ExpressionType nodeType, Type type) { // Can't enforce anything that V1 didn't if (_legacyCtorSupportTable == null) { Interlocked.CompareExchange( ref _legacyCtorSupportTable, new ConditionalWeakTable (), null ); } _legacyCtorSupportTable.Add(this, new ExtensionInfo(nodeType, type)); } #endif /// /// Constructs a new instance of protected Expression() { } ///. /// /// The public virtual ExpressionType NodeType { get { #if !MICROSOFT_SCRIPTING_CORE ExtensionInfo extInfo; if (_legacyCtorSupportTable != null && _legacyCtorSupportTable.TryGetValue(this, out extInfo)) { return extInfo.NodeType; } #endif // the extension expression failed to override NodeType throw Error.ExtensionNodeMustOverrideProperty("Expression.NodeType"); } } ///of the . /// /// The [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1721:PropertyNamesShouldNotMatchGetMethods")] public virtual Type Type { get { #if !MICROSOFT_SCRIPTING_CORE ExtensionInfo extInfo; if (_legacyCtorSupportTable != null && _legacyCtorSupportTable.TryGetValue(this, out extInfo)) { return extInfo.Type; } #endif // the extension expression failed to override Type throw Error.ExtensionNodeMustOverrideProperty("Expression.Type"); } } ///of the value represented by this . /// /// Indicates that the node can be reduced to a simpler node. If this /// returns true, Reduce() can be called to produce the reduced form. /// public virtual bool CanReduce { get { return false; } } ////// Reduces this node to a simpler expression. If CanReduce returns /// true, this should return a valid expression. This method is /// allowed to return another node which itself must be reduced. /// ///The reduced expression. public virtual Expression Reduce() { if (CanReduce) throw Error.ReducibleMustOverrideReduce(); return this; } ////// Reduces the node and then calls the visitor delegate on the reduced expression. /// Throws an exception if the node isn't reducible. /// /// An instance of. /// The expression being visited, or an expression which should replace it in the tree. ////// Override this method to provide logic to walk the node's children. /// A typical implementation will call visitor.Visit on each of its /// children, and if any of them change, should return a new copy of /// itself with the modified children. /// protected internal virtual Expression VisitChildren(ExpressionVisitor visitor) { if (!CanReduce) throw Error.MustBeReducible(); return visitor.Visit(ReduceAndCheck()); } ////// Dispatches to the specific visit method for this node type. For /// example, /// The visitor to visit this node with. ///will call into /// . /// The result of visiting this node. ////// This default implementation for protected internal virtual Expression Accept(ExpressionVisitor visitor) { return visitor.VisitExtension(this); } ////// nodes will call . /// Override this method to call into a more specific method on a derived /// visitor class of ExprressionVisitor. However, it should still /// support unknown visitors by calling VisitExtension. /// /// Reduces this node to a simpler expression. If CanReduce returns /// true, this should return a valid expression. This method is /// allowed to return another node which itself must be reduced. /// ///The reduced expression. ////// Unlike Reduce, this method checks that the reduced node satisfies /// certain invariants. /// public Expression ReduceAndCheck() { if (!CanReduce) throw Error.MustBeReducible(); var newNode = Reduce(); // 1. Reduction must return a new, non-null node // 2. Reduction must return a new node whose result type can be assigned to the type of the original node if (newNode == null || newNode == this) throw Error.MustReduceToDifferent(); if (!TypeUtils.AreReferenceAssignable(Type, newNode.Type)) throw Error.ReducedNotCompatible(); return newNode; } ////// Reduces the expression to a known node type (i.e. not an Extension node) /// or simply returns the expression if it is already a known type. /// ///The reduced expression. public Expression ReduceExtensions() { var node = this; while (node.NodeType == ExpressionType.Extension) { node = node.ReduceAndCheck(); } return node; } ////// Creates a ///representation of the Expression. /// A public override string ToString() { return ExpressionStringBuilder.ExpressionToString(this); } #if MICROSOFT_SCRIPTING_CORE ///representation of the Expression. /// Writes a /// Arepresentation of the to a . /// that will be used to build the string representation. public void DumpExpression(TextWriter writer) { DebugViewWriter.WriteTo(this, writer); } /// /// Creates a ///representation of the Expression. /// A public string DebugView { #else private string DebugView { #endif get { using (System.IO.StringWriter writer = new System.IO.StringWriter(CultureInfo.CurrentCulture)) { DebugViewWriter.WriteTo(this, writer); return writer.ToString(); } } } ///representation of the Expression. /// Helper used for ensuring we only return 1 instance of a ReadOnlyCollection of T. /// /// This is called from various methods where we internally hold onto an IList of T /// or a readonly collection of T. We check to see if we've already returned a /// readonly collection of T and if so simply return the other one. Otherwise we do /// a thread-safe replacement of the list w/ a readonly collection which wraps it. /// /// Ultimately this saves us from having to allocate a ReadOnlyCollection for our /// data types because the compiler is capable of going directly to the IList of T. /// internal static ReadOnlyCollectionReturnReadOnly (ref IList collection) { IList value = collection; // if it's already read-only just return it. ReadOnlyCollection res = value as ReadOnlyCollection ; if (res != null) { return res; } // otherwise make sure only readonly collection every gets exposed Interlocked.CompareExchange >( ref collection, value.ToReadOnly(), value ); // and return it return (ReadOnlyCollection )collection; } /// /// Helper used for ensuring we only return 1 instance of a ReadOnlyCollection of T. /// /// This is similar to the ReturnReadOnly of T. This version supports nodes which hold /// onto multiple Expressions where one is typed to object. That object field holds either /// an expression or a ReadOnlyCollection of Expressions. When it holds a ReadOnlyCollection /// the IList which backs it is a ListArgumentProvider which uses the Expression which /// implements IArgumentProvider to get 2nd and additional values. The ListArgumentProvider /// continues to hold onto the 1st expression. /// /// This enables users to get the ReadOnlyCollection w/o it consuming more memory than if /// it was just an array. Meanwhile The DLR internally avoids accessing which would force /// the readonly collection to be created resulting in a typical memory savings. /// internal static ReadOnlyCollectionReturnReadOnly(IArgumentProvider provider, ref object collection) { Expression tObj = collection as Expression; if (tObj != null) { // otherwise make sure only one readonly collection ever gets exposed Interlocked.CompareExchange( ref collection, new ReadOnlyCollection (new ListArgumentProvider(provider, tObj)), tObj ); } // and return what is not guaranteed to be a readonly collection return (ReadOnlyCollection )collection; } /// /// Helper which is used for specialized subtypes which use ReturnReadOnly(ref object, ...). /// This is the reverse version of ReturnReadOnly which takes an IArgumentProvider. /// /// This is used to return the 1st argument. The 1st argument is typed as object and either /// contains a ReadOnlyCollection or the Expression. We check for the Expression and if it's /// present we return that, otherwise we return the 1st element of the ReadOnlyCollection. /// internal static T ReturnObject(object collectionOrT) where T : class { T t = collectionOrT as T; if (t != null) { return t; } return ((ReadOnlyCollection )collectionOrT)[0]; } private static void RequiresCanRead(Expression expression, string paramName) { if (expression == null) { throw new ArgumentNullException(paramName); } // validate that we can read the node switch (expression.NodeType) { case ExpressionType.Index: IndexExpression index = (IndexExpression)expression; if (index.Indexer != null && !index.Indexer.CanRead) { throw new ArgumentException(Strings.ExpressionMustBeReadable, paramName); } break; case ExpressionType.MemberAccess: MemberExpression member = (MemberExpression)expression; MemberInfo memberInfo = member.Member; if (memberInfo.MemberType == MemberTypes.Property) { PropertyInfo prop = (PropertyInfo)memberInfo; if (!prop.CanRead) { throw new ArgumentException(Strings.ExpressionMustBeReadable, paramName); } } break; } } private static void RequiresCanRead(IEnumerable items, string paramName) { if (items != null) { // this is called a lot, avoid allocating an enumerator if we can... IList listItems = items as IList ; if (listItems != null) { for (int i = 0; i < listItems.Count; i++) { RequiresCanRead(listItems[i], paramName); } return; } foreach (var i in items) { RequiresCanRead(i, paramName); } } } private static void RequiresCanWrite(Expression expression, string paramName) { if (expression == null) { throw new ArgumentNullException(paramName); } bool canWrite = false; switch (expression.NodeType) { case ExpressionType.Index: IndexExpression index = (IndexExpression)expression; if (index.Indexer != null) { canWrite = index.Indexer.CanWrite; } else { canWrite = true; } break; case ExpressionType.MemberAccess: MemberExpression member = (MemberExpression)expression; switch (member.Member.MemberType) { case MemberTypes.Property: PropertyInfo prop = (PropertyInfo)member.Member; canWrite = prop.CanWrite; break; case MemberTypes.Field: FieldInfo field = (FieldInfo)member.Member; canWrite = !(field.IsInitOnly || field.IsLiteral); break; } break; case ExpressionType.Parameter: canWrite = true; break; } if (!canWrite) { throw new ArgumentException(Strings.ExpressionMustBeWriteable, paramName); } } } } // 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
- ScrollBar.cs
- DBDataPermission.cs
- CodeEntryPointMethod.cs
- TraceHwndHost.cs
- PrintDialog.cs
- PrefixQName.cs
- Message.cs
- HasCopySemanticsAttribute.cs
- Int64Animation.cs
- ForwardPositionQuery.cs
- InternalPermissions.cs
- VisualStyleRenderer.cs
- ByteStack.cs
- TypedAsyncResult.cs
- RoleService.cs
- BitmapEffectvisualstate.cs
- OdbcCommandBuilder.cs
- DSASignatureDeformatter.cs
- ResourceExpression.cs
- storepermission.cs
- TreeNodeCollectionEditor.cs
- DataGridViewRowHeightInfoNeededEventArgs.cs
- TextEndOfLine.cs
- ChineseLunisolarCalendar.cs
- TraceListeners.cs
- ImmutableObjectAttribute.cs
- Type.cs
- Proxy.cs
- FlowDocumentReaderAutomationPeer.cs
- CacheEntry.cs
- DragDrop.cs
- MatrixUtil.cs
- AdapterUtil.cs
- EntityClassGenerator.cs
- TemplateBindingExpression.cs
- recordstate.cs
- UserControlCodeDomTreeGenerator.cs
- Interlocked.cs
- TreeViewBindingsEditorForm.cs
- HeaderCollection.cs
- BaseServiceProvider.cs
- DateTime.cs
- WindowsGrip.cs
- ReaderWriterLock.cs
- PropertyOverridesDialog.cs
- EraserBehavior.cs
- GiveFeedbackEvent.cs
- RecordsAffectedEventArgs.cs
- JoinCqlBlock.cs
- IfAction.cs
- PageMediaType.cs
- DataBindingList.cs
- ExceptionUtil.cs
- XAMLParseException.cs
- ApplicationManager.cs
- TreeNodeConverter.cs
- Trigger.cs
- ClientUtils.cs
- DoubleCollection.cs
- XamlFilter.cs
- XPathSelfQuery.cs
- BinaryObjectWriter.cs
- ScriptHandlerFactory.cs
- EtwTrackingParticipant.cs
- TextRunCache.cs
- VirtualPath.cs
- Vars.cs
- Single.cs
- GlyphRunDrawing.cs
- NetworkInformationException.cs
- CookielessHelper.cs
- ActivityMetadata.cs
- TraversalRequest.cs
- FixedSOMTableRow.cs
- UniqueIdentifierService.cs
- ItemCollection.cs
- Highlights.cs
- EntityDescriptor.cs
- UInt32.cs
- RecordsAffectedEventArgs.cs
- WebPartMenuStyle.cs
- ElementAction.cs
- DataObjectEventArgs.cs
- ConditionalAttribute.cs
- RightNameExpirationInfoPair.cs
- ValueType.cs
- JsonByteArrayDataContract.cs
- ProviderCommandInfoUtils.cs
- CodeMemberField.cs
- PropertyItem.cs
- Merger.cs
- _OSSOCK.cs
- BreadCrumbTextConverter.cs
- ReadOnlyCollection.cs
- DeflateEmulationStream.cs
- UnsignedPublishLicense.cs
- WebReferencesBuildProvider.cs
- DataGridViewCellStyleChangedEventArgs.cs
- QilFactory.cs
- BulletedListDesigner.cs