Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / DataWeb / Client / System / Data / Services / Client / ProjectionPathBuilder.cs / 1305376 / ProjectionPathBuilder.cs
//----------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Provides a class that can materialize ATOM entries into typed
// objects, while maintaining a log of changes done.
//
//---------------------------------------------------------------------
namespace System.Data.Services.Client
{
#region Namespaces.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Linq.Expressions;
#endregion Namespaces.
///
/// Use this class to help keep track of projection paths built
/// while compiling a projection-based materialization plan.
///
internal class ProjectionPathBuilder
{
#region Private fields.
/// Stack of whether entities are in scope.
private readonly Stack entityInScope;
/// Registers rewrites for member initialization blocks.
private readonly List rewrites;
/// Stack of lambda expressions in scope.
private readonly Stack parameterExpressions;
///
/// Stack of expected type expression for .
///
private readonly Stack parameterExpressionTypes;
/// Stack of 'entry' parameter expressions.
private readonly Stack parameterEntries;
/// Stack of projection (target-tree) types for parameters.
private readonly Stack parameterProjectionTypes;
#endregion Private fields.
#region Constructors.
/// Initializes a new instance.
internal ProjectionPathBuilder()
{
this.entityInScope = new Stack();
this.rewrites = new List();
this.parameterExpressions = new Stack();
this.parameterExpressionTypes = new Stack();
this.parameterEntries = new Stack();
this.parameterProjectionTypes = new Stack();
}
#endregion Constructors.
#region Internal properties.
/// Whether the current scope is acting on an entity.
internal bool CurrentIsEntity
{
get { return this.entityInScope.Peek(); }
}
/// Expression for the expected type parameter.
internal Expression ExpectedParamTypeInScope
{
get
{
Debug.Assert(this.parameterExpressionTypes.Count > 0, "this.parameterExpressionTypes.Count > 0");
return this.parameterExpressionTypes.Peek();
}
}
/// Whether any rewrites have been registered.
internal bool HasRewrites
{
get { return this.rewrites.Count > 0; }
}
/// Expression for the entity parameter in the source tree lambda.
internal Expression LambdaParameterInScope
{
get
{
return this.parameterExpressions.Peek();
}
}
/// Expression for the entry parameter in the target tree.
internal Expression ParameterEntryInScope
{
get
{
return this.parameterEntries.Peek();
}
}
#endregion Internal properties.
#region Methods.
/// Provides a string representation of this object.
/// String representation of this object.
public override string ToString()
{
string result = "ProjectionPathBuilder: ";
if (this.parameterExpressions.Count == 0)
{
result += "(empty)";
}
else
{
result +=
"entity:" + this.CurrentIsEntity +
" param:" + this.ParameterEntryInScope;
}
return result;
}
/// Records that a lambda scope has been entered when visiting a projection.
/// Lambda being visited.
/// Expression to the entry parameter from the target tree.
/// Expression to the entry-expected-type from the target tree.
internal void EnterLambdaScope(LambdaExpression lambda, Expression entry, Expression expectedType)
{
Debug.Assert(lambda != null, "lambda != null");
Debug.Assert(lambda.Parameters.Count == 1, "lambda.Parameters.Count == 1");
ParameterExpression param = lambda.Parameters[0];
Type projectionType = lambda.Body.Type;
bool isEntityType = ClientType.CheckElementTypeIsEntity(projectionType);
this.entityInScope.Push(isEntityType);
this.parameterExpressions.Push(param);
this.parameterExpressionTypes.Push(expectedType);
this.parameterEntries.Push(entry);
this.parameterProjectionTypes.Push(projectionType);
}
///
/// Records that a member initialization expression has been entered
/// when visting a projection.
///
/// Expression for initialization.
internal void EnterMemberInit(MemberInitExpression init)
{
bool isEntityType = ClientType.CheckElementTypeIsEntity(init.Type);
this.entityInScope.Push(isEntityType);
}
/// Gets a rewrite for the specified expression; null if none is found.
/// Expression to match.
/// A rewrite for the expression; possibly null.
internal Expression GetRewrite(Expression expression)
{
Debug.Assert(expression != null, "expression != null");
List names = new List();
while (expression.NodeType == ExpressionType.MemberAccess)
{
MemberExpression member = (MemberExpression)expression;
names.Add(member.Member.Name);
expression = member.Expression;
}
Expression result = null;
foreach (var rewrite in this.rewrites)
{
if (rewrite.Root != expression)
{
continue;
}
if (names.Count != rewrite.MemberNames.Length)
{
continue;
}
bool match = true;
for (int i = 0; i < names.Count && i < rewrite.MemberNames.Length; i++)
{
if (names[names.Count - i - 1] != rewrite.MemberNames[i])
{
match = false;
break;
}
}
if (match)
{
result = rewrite.RewriteExpression;
break;
}
}
return result;
}
/// Records that a lambda scope has been left when visting a projection.
internal void LeaveLambdaScope()
{
this.entityInScope.Pop();
this.parameterExpressions.Pop();
this.parameterExpressionTypes.Pop();
this.parameterEntries.Pop();
this.parameterProjectionTypes.Pop();
}
///
/// Records that a member initialization expression has been left when
/// visting a projection.
///
internal void LeaveMemberInit()
{
this.entityInScope.Pop();
}
/// Registers a member initialization rewrite.
/// Root of member access path, typically a source tree parameter of entity type.
/// Sequence of names to match.
/// Rewrite expression for names.
internal void RegisterRewrite(Expression root, string[] names, Expression rewriteExpression)
{
Debug.Assert(root != null, "root != null");
Debug.Assert(names != null, "names != null");
Debug.Assert(rewriteExpression != null, "rewriteExpression != null");
this.rewrites.Add(new MemberInitRewrite() { Root = root, MemberNames = names, RewriteExpression = rewriteExpression });
this.parameterEntries.Push(rewriteExpression);
}
/// Revokes the latest rewrite registered on the specified .
/// Root of rewrites to revoke.
/// Names to revoke.
internal void RevokeRewrite(Expression root, string[] names)
{
Debug.Assert(root != null, "root != null");
for (int i = 0; i < this.rewrites.Count; i++)
{
if (this.rewrites[i].Root != root)
{
continue;
}
if (names.Length != this.rewrites[i].MemberNames.Length)
{
continue;
}
bool match = true;
for (int j = 0; j < names.Length; j++)
{
if (names[j] != this.rewrites[i].MemberNames[j])
{
match = false;
break;
}
}
if (match)
{
this.rewrites.RemoveAt(i);
this.parameterEntries.Pop();
return;
}
}
}
#endregion Methods.
#region Inner types.
/// Use this class to record how rewrites should occur under nested member initializations.
internal class MemberInitRewrite
{
/// Sequence of member names to match.
internal string[] MemberNames
{
get;
set;
}
/// Root of member access path, typically a source tree parameter of entity type.
internal Expression Root
{
get;
set;
}
/// Rewrite expressions for the last member path.
internal Expression RewriteExpression
{
get;
set;
}
}
#endregion Inner types.
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//----------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Provides a class that can materialize ATOM entries into typed
// objects, while maintaining a log of changes done.
//
//---------------------------------------------------------------------
namespace System.Data.Services.Client
{
#region Namespaces.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Linq.Expressions;
#endregion Namespaces.
///
/// Use this class to help keep track of projection paths built
/// while compiling a projection-based materialization plan.
///
internal class ProjectionPathBuilder
{
#region Private fields.
/// Stack of whether entities are in scope.
private readonly Stack entityInScope;
/// Registers rewrites for member initialization blocks.
private readonly List rewrites;
/// Stack of lambda expressions in scope.
private readonly Stack parameterExpressions;
///
/// Stack of expected type expression for .
///
private readonly Stack parameterExpressionTypes;
/// Stack of 'entry' parameter expressions.
private readonly Stack parameterEntries;
/// Stack of projection (target-tree) types for parameters.
private readonly Stack parameterProjectionTypes;
#endregion Private fields.
#region Constructors.
/// Initializes a new instance.
internal ProjectionPathBuilder()
{
this.entityInScope = new Stack();
this.rewrites = new List();
this.parameterExpressions = new Stack();
this.parameterExpressionTypes = new Stack();
this.parameterEntries = new Stack();
this.parameterProjectionTypes = new Stack();
}
#endregion Constructors.
#region Internal properties.
/// Whether the current scope is acting on an entity.
internal bool CurrentIsEntity
{
get { return this.entityInScope.Peek(); }
}
/// Expression for the expected type parameter.
internal Expression ExpectedParamTypeInScope
{
get
{
Debug.Assert(this.parameterExpressionTypes.Count > 0, "this.parameterExpressionTypes.Count > 0");
return this.parameterExpressionTypes.Peek();
}
}
/// Whether any rewrites have been registered.
internal bool HasRewrites
{
get { return this.rewrites.Count > 0; }
}
/// Expression for the entity parameter in the source tree lambda.
internal Expression LambdaParameterInScope
{
get
{
return this.parameterExpressions.Peek();
}
}
/// Expression for the entry parameter in the target tree.
internal Expression ParameterEntryInScope
{
get
{
return this.parameterEntries.Peek();
}
}
#endregion Internal properties.
#region Methods.
/// Provides a string representation of this object.
/// String representation of this object.
public override string ToString()
{
string result = "ProjectionPathBuilder: ";
if (this.parameterExpressions.Count == 0)
{
result += "(empty)";
}
else
{
result +=
"entity:" + this.CurrentIsEntity +
" param:" + this.ParameterEntryInScope;
}
return result;
}
/// Records that a lambda scope has been entered when visiting a projection.
/// Lambda being visited.
/// Expression to the entry parameter from the target tree.
/// Expression to the entry-expected-type from the target tree.
internal void EnterLambdaScope(LambdaExpression lambda, Expression entry, Expression expectedType)
{
Debug.Assert(lambda != null, "lambda != null");
Debug.Assert(lambda.Parameters.Count == 1, "lambda.Parameters.Count == 1");
ParameterExpression param = lambda.Parameters[0];
Type projectionType = lambda.Body.Type;
bool isEntityType = ClientType.CheckElementTypeIsEntity(projectionType);
this.entityInScope.Push(isEntityType);
this.parameterExpressions.Push(param);
this.parameterExpressionTypes.Push(expectedType);
this.parameterEntries.Push(entry);
this.parameterProjectionTypes.Push(projectionType);
}
///
/// Records that a member initialization expression has been entered
/// when visting a projection.
///
/// Expression for initialization.
internal void EnterMemberInit(MemberInitExpression init)
{
bool isEntityType = ClientType.CheckElementTypeIsEntity(init.Type);
this.entityInScope.Push(isEntityType);
}
/// Gets a rewrite for the specified expression; null if none is found.
/// Expression to match.
/// A rewrite for the expression; possibly null.
internal Expression GetRewrite(Expression expression)
{
Debug.Assert(expression != null, "expression != null");
List names = new List();
while (expression.NodeType == ExpressionType.MemberAccess)
{
MemberExpression member = (MemberExpression)expression;
names.Add(member.Member.Name);
expression = member.Expression;
}
Expression result = null;
foreach (var rewrite in this.rewrites)
{
if (rewrite.Root != expression)
{
continue;
}
if (names.Count != rewrite.MemberNames.Length)
{
continue;
}
bool match = true;
for (int i = 0; i < names.Count && i < rewrite.MemberNames.Length; i++)
{
if (names[names.Count - i - 1] != rewrite.MemberNames[i])
{
match = false;
break;
}
}
if (match)
{
result = rewrite.RewriteExpression;
break;
}
}
return result;
}
/// Records that a lambda scope has been left when visting a projection.
internal void LeaveLambdaScope()
{
this.entityInScope.Pop();
this.parameterExpressions.Pop();
this.parameterExpressionTypes.Pop();
this.parameterEntries.Pop();
this.parameterProjectionTypes.Pop();
}
///
/// Records that a member initialization expression has been left when
/// visting a projection.
///
internal void LeaveMemberInit()
{
this.entityInScope.Pop();
}
/// Registers a member initialization rewrite.
/// Root of member access path, typically a source tree parameter of entity type.
/// Sequence of names to match.
/// Rewrite expression for names.
internal void RegisterRewrite(Expression root, string[] names, Expression rewriteExpression)
{
Debug.Assert(root != null, "root != null");
Debug.Assert(names != null, "names != null");
Debug.Assert(rewriteExpression != null, "rewriteExpression != null");
this.rewrites.Add(new MemberInitRewrite() { Root = root, MemberNames = names, RewriteExpression = rewriteExpression });
this.parameterEntries.Push(rewriteExpression);
}
/// Revokes the latest rewrite registered on the specified .
/// Root of rewrites to revoke.
/// Names to revoke.
internal void RevokeRewrite(Expression root, string[] names)
{
Debug.Assert(root != null, "root != null");
for (int i = 0; i < this.rewrites.Count; i++)
{
if (this.rewrites[i].Root != root)
{
continue;
}
if (names.Length != this.rewrites[i].MemberNames.Length)
{
continue;
}
bool match = true;
for (int j = 0; j < names.Length; j++)
{
if (names[j] != this.rewrites[i].MemberNames[j])
{
match = false;
break;
}
}
if (match)
{
this.rewrites.RemoveAt(i);
this.parameterEntries.Pop();
return;
}
}
}
#endregion Methods.
#region Inner types.
/// Use this class to record how rewrites should occur under nested member initializations.
internal class MemberInitRewrite
{
/// Sequence of member names to match.
internal string[] MemberNames
{
get;
set;
}
/// Root of member access path, typically a source tree parameter of entity type.
internal Expression Root
{
get;
set;
}
/// Rewrite expressions for the last member path.
internal Expression RewriteExpression
{
get;
set;
}
}
#endregion Inner types.
}
}
// 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
- TableLayoutPanelDesigner.cs
- ChannelBinding.cs
- ThreadPoolTaskScheduler.cs
- DistributedTransactionPermission.cs
- RuleSettingsCollection.cs
- ButtonBase.cs
- MarkupObject.cs
- ValidationPropertyAttribute.cs
- AnimationClock.cs
- ConfigsHelper.cs
- EndpointAddress10.cs
- AsyncCompletedEventArgs.cs
- WorkflowInstanceProvider.cs
- PreloadedPackages.cs
- CurrencyWrapper.cs
- ImageIndexConverter.cs
- validationstate.cs
- EdmItemCollection.cs
- MD5.cs
- UserControlFileEditor.cs
- OracleConnectionStringBuilder.cs
- DataGridItemCollection.cs
- StringValidatorAttribute.cs
- BitmapEditor.cs
- ClientSettingsSection.cs
- SemaphoreSecurity.cs
- ProjectionCamera.cs
- EndpointAddress.cs
- ADConnectionHelper.cs
- BinaryMessageEncoder.cs
- MetadataExchangeBindings.cs
- TransformPatternIdentifiers.cs
- EnumBuilder.cs
- Vector3D.cs
- Localizer.cs
- ButtonBaseAutomationPeer.cs
- WindowsListViewGroup.cs
- MediaPlayer.cs
- List.cs
- CapabilitiesUse.cs
- Helper.cs
- CollectionsUtil.cs
- DetailsViewUpdateEventArgs.cs
- DecoderFallback.cs
- EncodingTable.cs
- FormView.cs
- Nullable.cs
- MasterPageBuildProvider.cs
- SHA1.cs
- NullableConverter.cs
- CommandValueSerializer.cs
- JournalEntryListConverter.cs
- GridEntryCollection.cs
- IconConverter.cs
- Window.cs
- ObjectDataSource.cs
- SystemException.cs
- GeneralTransform3DTo2DTo3D.cs
- CommandField.cs
- OutputCacheProviderCollection.cs
- Misc.cs
- WebPartConnectionsConfigureVerb.cs
- DefaultParameterValueAttribute.cs
- ZoneLinkButton.cs
- cookie.cs
- DeobfuscatingStream.cs
- XmlDataDocument.cs
- TextRenderer.cs
- EntryPointNotFoundException.cs
- ResourceDescriptionAttribute.cs
- SmiContext.cs
- OverlappedAsyncResult.cs
- PageSetupDialog.cs
- OptimalBreakSession.cs
- SafeArrayRankMismatchException.cs
- ExpandoClass.cs
- LinkedResourceCollection.cs
- AbstractSvcMapFileLoader.cs
- Win32Interop.cs
- UpdateTracker.cs
- Size3D.cs
- ArgumentOutOfRangeException.cs
- BufferBuilder.cs
- COM2ExtendedBrowsingHandler.cs
- ObjectStateFormatter.cs
- ShaperBuffers.cs
- DataGridViewRowEventArgs.cs
- DetailsViewPageEventArgs.cs
- StringUtil.cs
- DbParameterCollectionHelper.cs
- PropertyMapper.cs
- Button.cs
- CodeAttributeDeclarationCollection.cs
- PrintController.cs
- DriveNotFoundException.cs
- PasswordBoxAutomationPeer.cs
- DataSourceHelper.cs
- SqlBuilder.cs
- SqlOuterApplyReducer.cs
- util.cs