Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / DLinq / Dlinq / SqlClient / Query / TypeSource.cs / 1305376 / TypeSource.cs
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq.Expressions;
using System.Linq;
using System.Reflection;
using System.Data.Linq;
using System.Data.Linq.Mapping;
using System.Data.Linq.Provider;
using System.Diagnostics.CodeAnalysis;
namespace System.Data.Linq.SqlClient {
///
/// Method used for dealing with dynamic types. The ClrType of SqlNode is the
/// statically known type originating in the source expression tree. For methods
/// like GetType(), we need to know the dynamic type that will be constructed.
///
internal static class TypeSource {
private class Visitor : SqlVisitor {
class UnwrapStack {
public UnwrapStack(UnwrapStack last, bool unwrap) {
Last = last;
Unwrap = unwrap;
}
public UnwrapStack Last { get; private set; }
public bool Unwrap { get; private set; }
}
UnwrapStack UnwrapSequences;
internal SqlExpression sourceExpression;
internal Type sourceType;
[SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity", Justification="These issues are related to our use of if-then and case statements for node types, which adds to the complexity count however when reviewed they are easy to navigate and understand.")]
internal override SqlNode Visit(SqlNode node) {
if (node == null)
return null;
sourceExpression = node as SqlExpression;
if (sourceExpression != null) {
Type type = sourceExpression.ClrType;
UnwrapStack unwrap = this.UnwrapSequences;
while (unwrap != null) {
if (unwrap.Unwrap) {
type = TypeSystem.GetElementType(type);
}
unwrap = unwrap.Last;
}
sourceType = type;
}
if (sourceType != null && TypeSystem.GetNonNullableType(sourceType).IsValueType) {
return node; // Value types can't also have a dynamic type.
}
if (sourceType != null && TypeSystem.HasIEnumerable(sourceType)) {
return node; // Sequences can't be polymorphic.
}
switch (node.NodeType) {
case SqlNodeType.ScalarSubSelect:
case SqlNodeType.Multiset:
case SqlNodeType.Element:
case SqlNodeType.SearchedCase:
case SqlNodeType.ClientCase:
case SqlNodeType.SimpleCase:
case SqlNodeType.Member:
case SqlNodeType.DiscriminatedType:
case SqlNodeType.New:
case SqlNodeType.FunctionCall:
case SqlNodeType.MethodCall:
case SqlNodeType.Convert: // Object identity does not survive convert. It does survive Cast.
// Dig no further.
return node;
case SqlNodeType.TypeCase:
sourceType = ((SqlTypeCase)node).RowType.Type;
return node;
case SqlNodeType.Link:
sourceType = ((SqlLink)node).RowType.Type;
return node;
case SqlNodeType.Table:
sourceType = ((SqlTable)node).RowType.Type;
return node;
case SqlNodeType.Value:
SqlValue val = (SqlValue)node;
if (val.Value != null) {
// In some cases the ClrType of a Value node may
// differ from the actual runtime type of the value.
// Therefore, we ensure here that the correct type is set.
sourceType = val.Value.GetType();
}
return node;
}
return base.Visit(node);
}
internal override SqlSelect VisitSelect(SqlSelect select) {
/*
* We're travelling through of something like:
*
* SELECT
* FROM
*
* Inside the expression there may be a reference to that
* represents the dynamic type that we're trying to discover.
*
* In this case, the type relationship between AliasRef and Alias is
* T to IEnumerable.
*
* We need to remember to 'unpivot' the type of IEnumerable to
* get the correct dynamic type.
*
* Since SELECTs may be nested, we use a stack of pivots.
*
*/
this.UnwrapSequences = new UnwrapStack(this.UnwrapSequences, true);
VisitExpression(select.Selection);
this.UnwrapSequences = this.UnwrapSequences.Last;
return select;
}
internal override SqlExpression VisitAliasRef(SqlAliasRef aref) {
if (this.UnwrapSequences != null && this.UnwrapSequences.Unwrap) {
this.UnwrapSequences = new UnwrapStack(this.UnwrapSequences, false);
this.VisitAlias(aref.Alias);
this.UnwrapSequences = this.UnwrapSequences.Last;
} else {
this.VisitAlias(aref.Alias);
}
return aref;
}
internal override SqlExpression VisitColumnRef(SqlColumnRef cref) {
this.VisitColumn(cref.Column); // Travel through column references
return cref;
}
}
///
/// Get a MetaType that represents the dynamic type of the given node.
///
internal static MetaType GetSourceMetaType(SqlNode node, MetaModel model) {
Visitor v = new Visitor();
v.Visit(node);
Type type = v.sourceType;
type = TypeSystem.GetNonNullableType(type); // Emulate CLR's behavior: strip nullability from type.
return model.GetMetaType(type);
}
///
/// Retrieve the expression that will represent the _dynamic_ type of the
/// given expression. This is either a SqlDiscriminatedType or a SqlValue
/// of type Type.
///
internal static SqlExpression GetTypeSource(SqlExpression expr) {
Visitor v = new Visitor();
v.Visit(expr);
return v.sourceExpression;
}
}
}
// 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
- SrgsElementFactory.cs
- RightsManagementInformation.cs
- MessageSecurityOverHttp.cs
- ManifestResourceInfo.cs
- TextFormatterImp.cs
- GroupBox.cs
- HttpListenerResponse.cs
- CommandHelpers.cs
- EditorPartChrome.cs
- InternalRelationshipCollection.cs
- Table.cs
- xdrvalidator.cs
- ServiceDescriptions.cs
- XamlFigureLengthSerializer.cs
- XmlDataCollection.cs
- BamlMapTable.cs
- ChannelBinding.cs
- ErrorView.xaml.cs
- shaperfactoryquerycachekey.cs
- UserControlBuildProvider.cs
- NullRuntimeConfig.cs
- ExpressionWriter.cs
- ManualResetEventSlim.cs
- SortKey.cs
- WpfGeneratedKnownProperties.cs
- QuotedStringWriteStateInfo.cs
- GroupByExpressionRewriter.cs
- IDictionary.cs
- SqlDataSource.cs
- ReliableOutputConnection.cs
- Subordinate.cs
- BitmapEffectState.cs
- ClientFormsIdentity.cs
- ValueUtilsSmi.cs
- ReadOnlyDataSourceView.cs
- ImmutableObjectAttribute.cs
- ObjectViewEntityCollectionData.cs
- TableParaClient.cs
- Inflater.cs
- VisualBasicHelper.cs
- _ProxyRegBlob.cs
- ClientBuildManagerCallback.cs
- SByte.cs
- ScaleTransform.cs
- SpellerHighlightLayer.cs
- WindowsTokenRoleProvider.cs
- ThrowOnMultipleAssignment.cs
- IdentityModelStringsVersion1.cs
- DivideByZeroException.cs
- UnauthorizedWebPart.cs
- ExpressionBuilder.cs
- ResourcesGenerator.cs
- GlobalizationSection.cs
- DocumentSchemaValidator.cs
- QueryContinueDragEvent.cs
- ChannelManager.cs
- DeleteHelper.cs
- DataGridView.cs
- UnmanagedMarshal.cs
- CompareInfo.cs
- _AutoWebProxyScriptEngine.cs
- GeometryGroup.cs
- DateTimeFormatInfoScanner.cs
- QueryContext.cs
- InstanceData.cs
- DesignerProperties.cs
- ExpressionPrefixAttribute.cs
- SQLInt16.cs
- CodeIndexerExpression.cs
- ObjectListCommandCollection.cs
- CatalogPartCollection.cs
- CommandHelper.cs
- ClientBuildManager.cs
- TcpChannelHelper.cs
- TimersDescriptionAttribute.cs
- UriTemplateTrieLocation.cs
- SmtpNetworkElement.cs
- Font.cs
- VisualState.cs
- ProcessInfo.cs
- TimerElapsedEvenArgs.cs
- GeometryGroup.cs
- AttachedAnnotationChangedEventArgs.cs
- CssClassPropertyAttribute.cs
- KerberosSecurityTokenParameters.cs
- CommentAction.cs
- NetworkInformationException.cs
- FileSystemEventArgs.cs
- MetafileHeaderWmf.cs
- HttpHeaderCollection.cs
- InstanceNormalEvent.cs
- TabControlEvent.cs
- ViewBase.cs
- Point4DConverter.cs
- EventBindingService.cs
- MarshalByRefObject.cs
- Attribute.cs
- EditingCommands.cs
- WebPartDisplayModeCancelEventArgs.cs
- Module.cs