Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / DLinq / Dlinq / DataShape.cs / 1305376 / DataShape.cs
using System; using System.Collections.Generic; using System.Text; using System.Reflection; using System.Linq; using System.Linq.Expressions; using System.Collections; using System.Data.Linq.SqlClient; using System.Diagnostics.CodeAnalysis; namespace System.Data.Linq { sealed public class DataLoadOptions { bool frozen; Dictionaryincludes = new Dictionary (); Dictionary subqueries = new Dictionary (); /// /// Describe a property that is automatically loaded when the containing instance is loaded /// [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "[....]: Generic types are an important part of Linq APIs and they could not exist without nested generic support.")] [SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters", Justification = "[....]: Need to provide static typing.")] public void LoadWith(Expression > expression) { if (expression == null) { throw Error.ArgumentNull("expression"); } MemberInfo mi = GetLoadWithMemberInfo(expression); this.Preload(mi); } /// /// Describe a property that is automatically loaded when the containing instance is loaded /// public void LoadWith(LambdaExpression expression) { if (expression == null) { throw Error.ArgumentNull("expression"); } MemberInfo mi = GetLoadWithMemberInfo(expression); this.Preload(mi); } ////// Place a subquery on the given association. /// [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "[....]: Generic types are an important part of Linq APIs and they could not exist without nested generic support.")] [SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters", Justification = "[....]: Need to provide static typing.")] public void AssociateWith(Expression > expression) { if (expression == null) { throw Error.ArgumentNull("expression"); } this.AssociateWithInternal(expression); } /// /// Place a subquery on the given association. /// public void AssociateWith(LambdaExpression expression) { if (expression == null) { throw Error.ArgumentNull("expression"); } this.AssociateWithInternal(expression); } private void AssociateWithInternal(LambdaExpression expression) { // Strip the cast-to-object. Expression op = expression.Body; while (op.NodeType == ExpressionType.Convert || op.NodeType == ExpressionType.ConvertChecked) { op = ((UnaryExpression)op).Operand; } LambdaExpression lambda = Expression.Lambda(op, expression.Parameters.ToArray()); MemberInfo mi = Searcher.MemberInfoOf(lambda); this.Subquery(mi, lambda); } ////// Determines if the member is automatically loaded with its containing instances. /// /// The member this is automatically loaded. ///True if the member is automatically loaded. internal bool IsPreloaded(MemberInfo member) { if (member == null) { throw Error.ArgumentNull("member"); } return includes.ContainsKey(new MetaPosition(member)); } ////// Two shapes are equivalent if any of the following are true: /// (1) They are the same object instance /// (2) They are both null or empty /// (3) They contain the same preloaded members /// internal static bool ShapesAreEquivalent(DataLoadOptions ds1, DataLoadOptions ds2) { bool shapesAreSameOrEmpty = (ds1 == ds2) || ((ds1 == null || ds1.IsEmpty) && (ds2 == null || ds2.IsEmpty)); if (!shapesAreSameOrEmpty) { if (ds1 == null || ds2 == null || ds1.includes.Count != ds2.includes.Count) { return false; } foreach (MetaPosition metaPosition in ds2.includes.Keys) { if (!ds1.includes.ContainsKey(metaPosition)) { return false; } } } return true; } ////// Gets the subquery expression associated with the member. /// /// The member with the subquery. ///internal LambdaExpression GetAssociationSubquery(MemberInfo member) { if (member == null) { throw Error.ArgumentNull("member"); } LambdaExpression expression = null; subqueries.TryGetValue(new MetaPosition(member), out expression); return expression; } /// /// Freeze the shape. Any further attempts to modify the shape will result in /// an exception. /// internal void Freeze() { this.frozen = true; } ////// Describe a property that is automatically loaded when the containing instance is loaded /// internal void Preload(MemberInfo association) { if (association == null) { throw Error.ArgumentNull("association"); } if (this.frozen) { throw Error.IncludeNotAllowedAfterFreeze(); } this.includes.Add(new MetaPosition(association), association); ValidateTypeGraphAcyclic(); } ////// Place a subquery on the given association. /// private void Subquery(MemberInfo association, LambdaExpression subquery) { if (this.frozen) { throw Error.SubqueryNotAllowedAfterFreeze(); } subquery = (LambdaExpression)System.Data.Linq.SqlClient.Funcletizer.Funcletize(subquery); // Layering violation. ValidateSubqueryMember(association); ValidateSubqueryExpression(subquery); this.subqueries[new MetaPosition(association)] = subquery; } ////// If the lambda specified is of the form p.A, where p is the parameter /// and A is a member on p, the MemberInfo for A is returned. If /// the expression is not of this form, an exception is thrown. /// private static MemberInfo GetLoadWithMemberInfo(LambdaExpression lambda) { // When the specified member is a value type, there will be a conversion // to object that we need to strip Expression body = lambda.Body; if (body != null && (body.NodeType == ExpressionType.Convert || body.NodeType == ExpressionType.ConvertChecked)) { body = ((UnaryExpression)body).Operand; } MemberExpression mex = body as MemberExpression; if (mex != null && mex.Expression.NodeType == ExpressionType.Parameter) { return mex.Member; } else { throw Error.InvalidLoadOptionsLoadMemberSpecification(); } } private static class Searcher { static internal MemberInfo MemberInfoOf(LambdaExpression lambda) { Visitor v = new Visitor(); v.VisitLambda(lambda); return v.MemberInfo; } private class Visitor : System.Data.Linq.SqlClient.ExpressionVisitor { internal MemberInfo MemberInfo; internal override Expression VisitMemberAccess(MemberExpression m) { this.MemberInfo = m.Member; return base.VisitMemberAccess(m); } internal override Expression VisitMethodCall(MethodCallExpression m) { this.Visit(m.Object); foreach (Expression arg in m.Arguments) { this.Visit(arg); break; // Only follow the extension method 'this' } return m; } } } private void ValidateTypeGraphAcyclic() { IEnumerableedges = this.includes.Values; int removed = 0; for (int loop = 0; loop < this.includes.Count; ++loop) { // Build a list of all edge targets. HashSet edgeTargets = new HashSet (); foreach (MemberInfo edge in edges) { edgeTargets.Add(GetIncludeTarget(edge)); } // Remove all edges with sources matching no target. List newEdges = new List (); bool someRemoved = false; foreach (MemberInfo edge in edges) { if (edgeTargets.Where(et=>et.IsAssignableFrom(edge.DeclaringType) || edge.DeclaringType.IsAssignableFrom(et)).Any()) { newEdges.Add(edge); } else { ++removed; someRemoved = true; if (removed == this.includes.Count) return; } } if (!someRemoved) { throw Error.IncludeCycleNotAllowed(); // No edges removed, there must be a loop. } edges = newEdges; } throw new InvalidOperationException("Bug in ValidateTypeGraphAcyclic"); // Getting here means a bug. } private static Type GetIncludeTarget(MemberInfo mi) { Type mt = System.Data.Linq.SqlClient.TypeSystem.GetMemberType(mi); if (mt.IsGenericType) { return mt.GetGenericArguments()[0]; } return mt; } private static void ValidateSubqueryMember(MemberInfo mi) { Type memberType = System.Data.Linq.SqlClient.TypeSystem.GetMemberType(mi); if (memberType == null) { throw Error.SubqueryNotSupportedOn(mi); } if (!typeof(IEnumerable).IsAssignableFrom(memberType)) { throw Error.SubqueryNotSupportedOnType(mi.Name, mi.DeclaringType); } } private static void ValidateSubqueryExpression(LambdaExpression subquery) { if (!typeof(IEnumerable).IsAssignableFrom(subquery.Body.Type)) { throw Error.SubqueryMustBeSequence(); } new SubqueryValidator().VisitLambda(subquery); } /// /// Ensure that the subquery follows the rules for subqueries. /// private class SubqueryValidator : System.Data.Linq.SqlClient.ExpressionVisitor { bool isTopLevel = true; internal override Expression VisitMethodCall(MethodCallExpression m) { bool was = isTopLevel; try { if (isTopLevel && !SubqueryRules.IsSupportedTopLevelMethod(m.Method)) throw Error.SubqueryDoesNotSupportOperator(m.Method.Name); isTopLevel = false; return base.VisitMethodCall(m); } finally { isTopLevel = was; } } } ////// Whether there have been LoadOptions specified. /// internal bool IsEmpty { get { return this.includes.Count == 0 && this.subqueries.Count == 0; } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved. using System; using System.Collections.Generic; using System.Text; using System.Reflection; using System.Linq; using System.Linq.Expressions; using System.Collections; using System.Data.Linq.SqlClient; using System.Diagnostics.CodeAnalysis; namespace System.Data.Linq { sealed public class DataLoadOptions { bool frozen; Dictionaryincludes = new Dictionary (); Dictionary subqueries = new Dictionary (); /// /// Describe a property that is automatically loaded when the containing instance is loaded /// [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "[....]: Generic types are an important part of Linq APIs and they could not exist without nested generic support.")] [SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters", Justification = "[....]: Need to provide static typing.")] public void LoadWith(Expression > expression) { if (expression == null) { throw Error.ArgumentNull("expression"); } MemberInfo mi = GetLoadWithMemberInfo(expression); this.Preload(mi); } /// /// Describe a property that is automatically loaded when the containing instance is loaded /// public void LoadWith(LambdaExpression expression) { if (expression == null) { throw Error.ArgumentNull("expression"); } MemberInfo mi = GetLoadWithMemberInfo(expression); this.Preload(mi); } ////// Place a subquery on the given association. /// [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "[....]: Generic types are an important part of Linq APIs and they could not exist without nested generic support.")] [SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters", Justification = "[....]: Need to provide static typing.")] public void AssociateWith(Expression > expression) { if (expression == null) { throw Error.ArgumentNull("expression"); } this.AssociateWithInternal(expression); } /// /// Place a subquery on the given association. /// public void AssociateWith(LambdaExpression expression) { if (expression == null) { throw Error.ArgumentNull("expression"); } this.AssociateWithInternal(expression); } private void AssociateWithInternal(LambdaExpression expression) { // Strip the cast-to-object. Expression op = expression.Body; while (op.NodeType == ExpressionType.Convert || op.NodeType == ExpressionType.ConvertChecked) { op = ((UnaryExpression)op).Operand; } LambdaExpression lambda = Expression.Lambda(op, expression.Parameters.ToArray()); MemberInfo mi = Searcher.MemberInfoOf(lambda); this.Subquery(mi, lambda); } ////// Determines if the member is automatically loaded with its containing instances. /// /// The member this is automatically loaded. ///True if the member is automatically loaded. internal bool IsPreloaded(MemberInfo member) { if (member == null) { throw Error.ArgumentNull("member"); } return includes.ContainsKey(new MetaPosition(member)); } ////// Two shapes are equivalent if any of the following are true: /// (1) They are the same object instance /// (2) They are both null or empty /// (3) They contain the same preloaded members /// internal static bool ShapesAreEquivalent(DataLoadOptions ds1, DataLoadOptions ds2) { bool shapesAreSameOrEmpty = (ds1 == ds2) || ((ds1 == null || ds1.IsEmpty) && (ds2 == null || ds2.IsEmpty)); if (!shapesAreSameOrEmpty) { if (ds1 == null || ds2 == null || ds1.includes.Count != ds2.includes.Count) { return false; } foreach (MetaPosition metaPosition in ds2.includes.Keys) { if (!ds1.includes.ContainsKey(metaPosition)) { return false; } } } return true; } ////// Gets the subquery expression associated with the member. /// /// The member with the subquery. ///internal LambdaExpression GetAssociationSubquery(MemberInfo member) { if (member == null) { throw Error.ArgumentNull("member"); } LambdaExpression expression = null; subqueries.TryGetValue(new MetaPosition(member), out expression); return expression; } /// /// Freeze the shape. Any further attempts to modify the shape will result in /// an exception. /// internal void Freeze() { this.frozen = true; } ////// Describe a property that is automatically loaded when the containing instance is loaded /// internal void Preload(MemberInfo association) { if (association == null) { throw Error.ArgumentNull("association"); } if (this.frozen) { throw Error.IncludeNotAllowedAfterFreeze(); } this.includes.Add(new MetaPosition(association), association); ValidateTypeGraphAcyclic(); } ////// Place a subquery on the given association. /// private void Subquery(MemberInfo association, LambdaExpression subquery) { if (this.frozen) { throw Error.SubqueryNotAllowedAfterFreeze(); } subquery = (LambdaExpression)System.Data.Linq.SqlClient.Funcletizer.Funcletize(subquery); // Layering violation. ValidateSubqueryMember(association); ValidateSubqueryExpression(subquery); this.subqueries[new MetaPosition(association)] = subquery; } ////// If the lambda specified is of the form p.A, where p is the parameter /// and A is a member on p, the MemberInfo for A is returned. If /// the expression is not of this form, an exception is thrown. /// private static MemberInfo GetLoadWithMemberInfo(LambdaExpression lambda) { // When the specified member is a value type, there will be a conversion // to object that we need to strip Expression body = lambda.Body; if (body != null && (body.NodeType == ExpressionType.Convert || body.NodeType == ExpressionType.ConvertChecked)) { body = ((UnaryExpression)body).Operand; } MemberExpression mex = body as MemberExpression; if (mex != null && mex.Expression.NodeType == ExpressionType.Parameter) { return mex.Member; } else { throw Error.InvalidLoadOptionsLoadMemberSpecification(); } } private static class Searcher { static internal MemberInfo MemberInfoOf(LambdaExpression lambda) { Visitor v = new Visitor(); v.VisitLambda(lambda); return v.MemberInfo; } private class Visitor : System.Data.Linq.SqlClient.ExpressionVisitor { internal MemberInfo MemberInfo; internal override Expression VisitMemberAccess(MemberExpression m) { this.MemberInfo = m.Member; return base.VisitMemberAccess(m); } internal override Expression VisitMethodCall(MethodCallExpression m) { this.Visit(m.Object); foreach (Expression arg in m.Arguments) { this.Visit(arg); break; // Only follow the extension method 'this' } return m; } } } private void ValidateTypeGraphAcyclic() { IEnumerableedges = this.includes.Values; int removed = 0; for (int loop = 0; loop < this.includes.Count; ++loop) { // Build a list of all edge targets. HashSet edgeTargets = new HashSet (); foreach (MemberInfo edge in edges) { edgeTargets.Add(GetIncludeTarget(edge)); } // Remove all edges with sources matching no target. List newEdges = new List (); bool someRemoved = false; foreach (MemberInfo edge in edges) { if (edgeTargets.Where(et=>et.IsAssignableFrom(edge.DeclaringType) || edge.DeclaringType.IsAssignableFrom(et)).Any()) { newEdges.Add(edge); } else { ++removed; someRemoved = true; if (removed == this.includes.Count) return; } } if (!someRemoved) { throw Error.IncludeCycleNotAllowed(); // No edges removed, there must be a loop. } edges = newEdges; } throw new InvalidOperationException("Bug in ValidateTypeGraphAcyclic"); // Getting here means a bug. } private static Type GetIncludeTarget(MemberInfo mi) { Type mt = System.Data.Linq.SqlClient.TypeSystem.GetMemberType(mi); if (mt.IsGenericType) { return mt.GetGenericArguments()[0]; } return mt; } private static void ValidateSubqueryMember(MemberInfo mi) { Type memberType = System.Data.Linq.SqlClient.TypeSystem.GetMemberType(mi); if (memberType == null) { throw Error.SubqueryNotSupportedOn(mi); } if (!typeof(IEnumerable).IsAssignableFrom(memberType)) { throw Error.SubqueryNotSupportedOnType(mi.Name, mi.DeclaringType); } } private static void ValidateSubqueryExpression(LambdaExpression subquery) { if (!typeof(IEnumerable).IsAssignableFrom(subquery.Body.Type)) { throw Error.SubqueryMustBeSequence(); } new SubqueryValidator().VisitLambda(subquery); } /// /// Ensure that the subquery follows the rules for subqueries. /// private class SubqueryValidator : System.Data.Linq.SqlClient.ExpressionVisitor { bool isTopLevel = true; internal override Expression VisitMethodCall(MethodCallExpression m) { bool was = isTopLevel; try { if (isTopLevel && !SubqueryRules.IsSupportedTopLevelMethod(m.Method)) throw Error.SubqueryDoesNotSupportOperator(m.Method.Name); isTopLevel = false; return base.VisitMethodCall(m); } finally { isTopLevel = was; } } } ////// Whether there have been LoadOptions specified. /// internal bool IsEmpty { get { return this.includes.Count == 0 && this.subqueries.Count == 0; } } } } // 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
- XmlHelper.cs
- QuadraticBezierSegment.cs
- WsdlInspector.cs
- DataTableNewRowEvent.cs
- XmlNode.cs
- XPathNodeList.cs
- SiteOfOriginContainer.cs
- KnownAssemblyEntry.cs
- SortDescription.cs
- ReadOnlyCollection.cs
- LogicalChannel.cs
- QilCloneVisitor.cs
- CodeDelegateCreateExpression.cs
- SamlDelegatingWriter.cs
- KnownTypesProvider.cs
- RSAPKCS1SignatureDeformatter.cs
- COM2IVsPerPropertyBrowsingHandler.cs
- _PooledStream.cs
- XmlArrayAttribute.cs
- PageParser.cs
- SharedUtils.cs
- Int32AnimationUsingKeyFrames.cs
- SendKeys.cs
- EmptyEnumerator.cs
- WebPageTraceListener.cs
- arabicshape.cs
- SettingsPropertyWrongTypeException.cs
- MimeMultiPart.cs
- LockedAssemblyCache.cs
- ScrollChrome.cs
- ToolboxItem.cs
- WrappedReader.cs
- StateDesigner.CommentLayoutGlyph.cs
- ServiceObjectContainer.cs
- ResponseBodyWriter.cs
- SqlClientPermission.cs
- CompileXomlTask.cs
- SqlParameterCollection.cs
- WebHostedComPlusServiceHost.cs
- UserInitiatedRoutedEventPermission.cs
- UnknownWrapper.cs
- DbSourceParameterCollection.cs
- ListViewItemMouseHoverEvent.cs
- MergeExecutor.cs
- PropertyDescriptorGridEntry.cs
- BufferBuilder.cs
- EventMappingSettings.cs
- AudioBase.cs
- XmlMtomReader.cs
- TerminatorSinks.cs
- ProcessHostServerConfig.cs
- ChangeInterceptorAttribute.cs
- StoryFragments.cs
- Cursor.cs
- AspCompat.cs
- RelationshipWrapper.cs
- WindowsSecurityToken.cs
- StylusPointPropertyUnit.cs
- SqlDataRecord.cs
- AutoSizeToolBoxItem.cs
- DiscoveryClientElement.cs
- RenderDataDrawingContext.cs
- DataIdProcessor.cs
- SendMessageContent.cs
- PhysicalFontFamily.cs
- XmlQuerySequence.cs
- FragmentQueryKB.cs
- OletxVolatileEnlistment.cs
- TextDecorationCollection.cs
- Assembly.cs
- TargetControlTypeCache.cs
- Base64Encoder.cs
- ObjectContext.cs
- VerificationAttribute.cs
- SafeEventLogWriteHandle.cs
- WindowsListViewItem.cs
- GacUtil.cs
- QuaternionAnimation.cs
- DataGrid.cs
- BufferedStream.cs
- MarkedHighlightComponent.cs
- LeafCellTreeNode.cs
- AddInDeploymentState.cs
- SendMailErrorEventArgs.cs
- EventWaitHandle.cs
- RemotingException.cs
- EventWaitHandleSecurity.cs
- COSERVERINFO.cs
- XPathScanner.cs
- RenamedEventArgs.cs
- DesignerProperties.cs
- TraceUtils.cs
- FileNotFoundException.cs
- DependencyObject.cs
- ComponentEvent.cs
- ErrorItem.cs
- ReferenceService.cs
- SamlAction.cs
- ContentElementCollection.cs
- controlskin.cs