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
- DbgUtil.cs
- StyleReferenceConverter.cs
- Transform.cs
- InputEventArgs.cs
- SqlDataSourceQueryEditor.cs
- TextEditorSpelling.cs
- WebPartsSection.cs
- XmlIlGenerator.cs
- SyndicationCategory.cs
- Label.cs
- Trace.cs
- ArrayExtension.cs
- ListViewAutomationPeer.cs
- EnvironmentPermission.cs
- ConfigXmlCDataSection.cs
- SizeFConverter.cs
- SqlConnectionString.cs
- MouseActionValueSerializer.cs
- AudioDeviceOut.cs
- DbMetaDataColumnNames.cs
- HttpListenerElement.cs
- Serializer.cs
- TraceHandler.cs
- ScriptReferenceBase.cs
- NonBatchDirectoryCompiler.cs
- Group.cs
- Bidi.cs
- TableLayoutPanelCellPosition.cs
- EntityKeyElement.cs
- CompilerWrapper.cs
- JsonObjectDataContract.cs
- StylusCaptureWithinProperty.cs
- DataSourceExpressionCollection.cs
- _DomainName.cs
- InputLanguage.cs
- TimeoutValidationAttribute.cs
- CryptoHandle.cs
- NativeMethodsCLR.cs
- RegexEditorDialog.cs
- EnumerableCollectionView.cs
- DataGridViewRowHeaderCell.cs
- Barrier.cs
- DbConvert.cs
- ApplicationId.cs
- RayMeshGeometry3DHitTestResult.cs
- WebPartRestoreVerb.cs
- RequestedSignatureDialog.cs
- ChildTable.cs
- Set.cs
- FixedTextView.cs
- FirewallWrapper.cs
- WebPartCancelEventArgs.cs
- QueryExpression.cs
- ModuleConfigurationInfo.cs
- DataKey.cs
- TransformerConfigurationWizardBase.cs
- AutomationEvent.cs
- GridView.cs
- XamlClipboardData.cs
- VisualStyleTypesAndProperties.cs
- MonitoringDescriptionAttribute.cs
- Utility.cs
- MsmqProcessProtocolHandler.cs
- PointHitTestResult.cs
- FixedSOMImage.cs
- NodeInfo.cs
- TreeViewCancelEvent.cs
- UpdatePanelTriggerCollection.cs
- SimpleType.cs
- IteratorDescriptor.cs
- keycontainerpermission.cs
- CompilerError.cs
- BackgroundFormatInfo.cs
- xmlsaver.cs
- FixedLineResult.cs
- XmlSchemaImporter.cs
- TemplateComponentConnector.cs
- DbFunctionCommandTree.cs
- XmlWriterSettings.cs
- ExpressionBuilderCollection.cs
- TextFormatterContext.cs
- Win32.cs
- Int16AnimationBase.cs
- PropertyPathWorker.cs
- DataReceivedEventArgs.cs
- JavaScriptObjectDeserializer.cs
- SqlDataSourceView.cs
- XamlToRtfParser.cs
- ServicesUtilities.cs
- SafeProcessHandle.cs
- GeneralTransform3DTo2DTo3D.cs
- MultiPageTextView.cs
- XmlEnumAttribute.cs
- CustomErrorsSection.cs
- ClientFormsIdentity.cs
- sqlinternaltransaction.cs
- ReflectPropertyDescriptor.cs
- SchemaImporterExtension.cs
- DocumentViewerBaseAutomationPeer.cs
- XPathChildIterator.cs