Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / DataEntity / System / Data / Common / EntitySql / TypeResolver.cs / 1305376 / TypeResolver.cs
//----------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// @owner [....]
// @backupOwner [....]
//---------------------------------------------------------------------
namespace System.Data.Common.EntitySql
{
using System;
using System.Globalization;
using System.Collections.Generic;
using System.Diagnostics;
using System.Data.Common;
using System.Data.Metadata.Edm;
using System.Data.Entity;
using System.Linq;
///
/// Represents eSQL metadata member expression class.
///
internal enum MetadataMemberClass
{
Type,
FunctionGroup,
InlineFunctionGroup,
Namespace
}
///
/// Abstract class representing an eSQL expression classified as .
///
internal abstract class MetadataMember : ExpressionResolution
{
protected MetadataMember(MetadataMemberClass @class, string name)
: base(ExpressionResolutionClass.MetadataMember)
{
Debug.Assert(!String.IsNullOrEmpty(name), "name must not be empty");
MetadataMemberClass = @class;
Name = name;
}
internal override string ExpressionClassName { get { return MetadataMemberExpressionClassName; } }
internal static string MetadataMemberExpressionClassName { get { return Strings.LocalizedMetadataMemberExpression; } }
internal readonly MetadataMemberClass MetadataMemberClass;
internal readonly string Name;
///
/// Return the name of the for error messages.
///
internal abstract string MetadataMemberClassName { get; }
internal static IEqualityComparer CreateMetadataMemberNameEqualityComparer(StringComparer stringComparer)
{
return new MetadataMemberNameEqualityComparer(stringComparer);
}
private sealed class MetadataMemberNameEqualityComparer : IEqualityComparer
{
private readonly StringComparer _stringComparer;
internal MetadataMemberNameEqualityComparer(StringComparer stringComparer)
{
_stringComparer = stringComparer;
}
bool IEqualityComparer.Equals(MetadataMember x, MetadataMember y)
{
Debug.Assert(x != null && y != null, "metadata members must not be null");
return _stringComparer.Equals(x.Name, y.Name);
}
int IEqualityComparer.GetHashCode(MetadataMember obj)
{
Debug.Assert(obj != null, "metadata member must not be null");
return _stringComparer.GetHashCode(obj.Name);
}
}
}
///
/// Represents an eSQL metadata member expression classified as .
///
internal sealed class MetadataNamespace : MetadataMember
{
internal MetadataNamespace(string name) : base(MetadataMemberClass.Namespace, name) { }
internal override string MetadataMemberClassName { get { return NamespaceClassName; } }
internal static string NamespaceClassName { get { return Strings.LocalizedNamespace; } }
}
///
/// Represents an eSQL metadata member expression classified as .
///
internal sealed class MetadataType : MetadataMember
{
internal MetadataType(string name, TypeUsage typeUsage)
: base(MetadataMemberClass.Type, name)
{
Debug.Assert(typeUsage != null, "typeUsage must not be null");
TypeUsage = typeUsage;
}
internal override string MetadataMemberClassName { get { return TypeClassName; } }
internal static string TypeClassName { get { return Strings.LocalizedType; } }
internal readonly TypeUsage TypeUsage;
}
///
/// Represents an eSQL metadata member expression classified as .
///
internal sealed class MetadataFunctionGroup : MetadataMember
{
internal MetadataFunctionGroup(string name, IList functionMetadata)
: base(MetadataMemberClass.FunctionGroup, name)
{
Debug.Assert(functionMetadata != null && functionMetadata.Count > 0, "FunctionMetadata must not be null or empty");
FunctionMetadata = functionMetadata;
}
internal override string MetadataMemberClassName { get { return FunctionGroupClassName; } }
internal static string FunctionGroupClassName { get { return Strings.LocalizedFunction; } }
internal readonly IList FunctionMetadata;
}
///
/// Represents an eSQL metadata member expression classified as .
///
internal sealed class InlineFunctionGroup : MetadataMember
{
internal InlineFunctionGroup(string name, IList functionMetadata)
: base(MetadataMemberClass.InlineFunctionGroup, name)
{
Debug.Assert(functionMetadata != null && functionMetadata.Count > 0, "FunctionMetadata must not be null or empty");
FunctionMetadata = functionMetadata;
}
internal override string MetadataMemberClassName { get { return InlineFunctionGroupClassName; } }
internal static string InlineFunctionGroupClassName { get { return Strings.LocalizedInlineFunction; } }
internal readonly IList FunctionMetadata;
}
///
/// Represents eSQL type and namespace name resolver.
///
internal sealed class TypeResolver
{
private readonly Perspective _perspective;
private readonly Dictionary _aliasedNamespaces;
private readonly HashSet _namespaces;
///
/// name -> list(overload)
///
private readonly Dictionary> _functionDefinitions;
private bool _includeInlineFunctions;
private bool _resolveLeftMostUnqualifiedNameAsNamespaceOnly;
///
/// Initializes TypeResolver instance
///
internal TypeResolver(Perspective perspective, StringComparer stringComparer)
{
EntityUtil.CheckArgumentNull(perspective, "perspective");
_perspective = perspective;
_aliasedNamespaces = new Dictionary(stringComparer);
_namespaces = new HashSet(MetadataMember.CreateMetadataMemberNameEqualityComparer(stringComparer));
_functionDefinitions = new Dictionary>(stringComparer);
_includeInlineFunctions = true;
_resolveLeftMostUnqualifiedNameAsNamespaceOnly = false;
}
///
/// Returns perspective.
///
internal Perspective Perspective
{
get { return _perspective; }
}
///
/// Returns namespace imports.
///
internal ICollection NamespaceImports
{
get { return _namespaces; }
}
///
/// Returns for .
///
internal TypeUsage StringType
{
get { return _perspective.MetadataWorkspace.GetCanonicalModelTypeUsage(PrimitiveTypeKind.String); }
}
///
/// Returns for .
///
internal TypeUsage BooleanType
{
get { return _perspective.MetadataWorkspace.GetCanonicalModelTypeUsage(PrimitiveTypeKind.Boolean); }
}
///
/// Returns for .
///
internal TypeUsage Int64Type
{
get { return _perspective.MetadataWorkspace.GetCanonicalModelTypeUsage(PrimitiveTypeKind.Int64); }
}
///
/// Adds an aliased namespace import.
///
internal void AddAliasedNamespaceImport(string alias, MetadataNamespace @namespace, ErrorContext errCtx)
{
if (_aliasedNamespaces.ContainsKey(alias))
{
throw EntityUtil.EntitySqlError(errCtx, Strings.NamespaceAliasAlreadyUsed(alias));
}
_aliasedNamespaces.Add(alias, @namespace);
}
///
/// Adds a non-aliased namespace import.
///
internal void AddNamespaceImport(MetadataNamespace @namespace, ErrorContext errCtx)
{
if (_namespaces.Contains(@namespace))
{
throw EntityUtil.EntitySqlError(errCtx, Strings.NamespaceAlreadyImported(@namespace.Name));
}
_namespaces.Add(@namespace);
}
#region Inline function declarations
///
/// Declares inline function in the query local metadata.
///
internal void DeclareInlineFunction(string name, InlineFunctionInfo functionInfo)
{
Debug.Assert(!String.IsNullOrEmpty(name), "name must not be null or empty");
Debug.Assert(functionInfo != null, "functionInfo != null");
List overloads;
if (!_functionDefinitions.TryGetValue(name, out overloads))
{
overloads = new List();
_functionDefinitions.Add(name, overloads);
}
//
// Check overload uniqueness.
//
if (overloads.Exists(overload =>
overload.Parameters.Select(p => p.ResultType).SequenceEqual(functionInfo.Parameters.Select(p => p.ResultType), TypeUsageStructuralComparer.Instance)))
{
throw EntityUtil.EntitySqlError(functionInfo.FunctionDefAst.ErrCtx, Strings.DuplicatedInlineFunctionOverload(name));
}
overloads.Add(functionInfo);
}
private sealed class TypeUsageStructuralComparer : IEqualityComparer
{
internal static readonly TypeUsageStructuralComparer Instance = new TypeUsageStructuralComparer();
private TypeUsageStructuralComparer() { }
public bool Equals(TypeUsage x, TypeUsage y)
{
return TypeSemantics.IsStructurallyEqual(x, y);
}
public int GetHashCode(TypeUsage obj)
{
Debug.Fail("Not implemented");
return 0;
}
}
#endregion
internal IDisposable EnterFunctionNameResolution(bool includeInlineFunctions)
{
bool savedIncludeInlineFunctions = _includeInlineFunctions;
_includeInlineFunctions = includeInlineFunctions;
return new Disposer(delegate { this._includeInlineFunctions = savedIncludeInlineFunctions; });
}
internal IDisposable EnterBackwardCompatibilityResolution()
{
Debug.Assert(!_resolveLeftMostUnqualifiedNameAsNamespaceOnly, "EnterBackwardCompatibilityResolution() is not reentrant.");
_resolveLeftMostUnqualifiedNameAsNamespaceOnly = true;
return new Disposer(delegate
{
Debug.Assert(this._resolveLeftMostUnqualifiedNameAsNamespaceOnly, "_resolveLeftMostUnqualifiedNameAsNamespaceOnly must be true.");
this._resolveLeftMostUnqualifiedNameAsNamespaceOnly = false;
});
}
internal MetadataMember ResolveMetadataMemberName(string[] name, ErrorContext errCtx)
{
Debug.Assert(name != null && name.Length > 0, "name must not be empty");
MetadataMember metadataMember;
if (name.Length == 1)
{
metadataMember = ResolveUnqualifiedName(name[0], false /* partOfQualifiedName */, errCtx);
}
else
{
metadataMember = ResolveFullyQualifiedName(name, name.Length, errCtx);
}
Debug.Assert(metadataMember != null, "metadata member name resolution must not return null");
return metadataMember;
}
internal MetadataMember ResolveMetadataMemberAccess(MetadataMember qualifier, string name, ErrorContext errCtx)
{
string fullName = GetFullName(qualifier.Name, name);
if (qualifier.MetadataMemberClass == MetadataMemberClass.Namespace)
{
//
// Try resolving as a type.
//
MetadataType type;
if (TryGetTypeFromMetadata(fullName, out type))
{
return type;
}
//
// Try resolving as a function.
//
MetadataFunctionGroup function;
if (TryGetFunctionFromMetadata(fullName, out function))
{
return function;
}
//
// Otherwise, resolve as a namespace.
//
return new MetadataNamespace(fullName);
}
else
{
throw EntityUtil.EntitySqlError(errCtx, Strings.InvalidMetadataMemberClassResolution(
qualifier.Name, qualifier.MetadataMemberClassName, MetadataNamespace.NamespaceClassName));
}
}
internal MetadataMember ResolveUnqualifiedName(string name, bool partOfQualifiedName, ErrorContext errCtx)
{
Debug.Assert(!String.IsNullOrEmpty(name), "name must not be empty");
//
// In the case of Name1.Name2...NameN and if backward compatibility mode is on, then resolve Name1 as namespace only, ignore any other possible resolutions.
//
bool resolveAsNamespaceOnly = partOfQualifiedName && _resolveLeftMostUnqualifiedNameAsNamespaceOnly;
//
// In the case of Name1.Name2...NameN, ignore functions while resolving Name1: functions don't have members.
//
bool includeFunctions = !partOfQualifiedName;
//
// Try resolving as an inline function.
//
InlineFunctionGroup inlineFunctionGroup;
if (!resolveAsNamespaceOnly &&
includeFunctions && TryGetInlineFunction(name, out inlineFunctionGroup))
{
return inlineFunctionGroup;
}
//
// Try resolving as a namespace alias.
//
MetadataNamespace aliasedNamespaceImport;
if (_aliasedNamespaces.TryGetValue(name, out aliasedNamespaceImport))
{
return aliasedNamespaceImport;
}
if (!resolveAsNamespaceOnly)
{
//
// Try resolving as a type or functionGroup in the global namespace or as an imported member.
// Throw if ambiguous.
//
MetadataType type = null;
MetadataFunctionGroup functionGroup = null;
//
// Try resolving in the global namespace.
//
if (!TryGetTypeFromMetadata(name, out type))
{
if (includeFunctions)
{
TryGetFunctionFromMetadata(name, out functionGroup);
}
}
//
// Try resolving as an imported member.
//
MetadataNamespace importedMemberNamespace = null;
foreach (MetadataNamespace namespaceImport in _namespaces)
{
string fullName = GetFullName(namespaceImport.Name, name);
MetadataType importedType;
if (TryGetTypeFromMetadata(fullName, out importedType))
{
if (type == null && functionGroup == null)
{
type = importedType;
importedMemberNamespace = namespaceImport;
}
else
{
throw AmbiguousMetadataMemberName(errCtx, name, namespaceImport, importedMemberNamespace);
}
}
MetadataFunctionGroup importedFunctionGroup;
if (includeFunctions && TryGetFunctionFromMetadata(fullName, out importedFunctionGroup))
{
if (type == null && functionGroup == null)
{
functionGroup = importedFunctionGroup;
importedMemberNamespace = namespaceImport;
}
else
{
throw AmbiguousMetadataMemberName(errCtx, name, namespaceImport, importedMemberNamespace);
}
}
}
if (type != null)
{
return type;
}
if (functionGroup != null)
{
return functionGroup;
}
}
//
// Otherwise, resolve as a namespace.
//
return new MetadataNamespace(name);
}
private MetadataMember ResolveFullyQualifiedName(string[] name, int length, ErrorContext errCtx)
{
Debug.Assert(name != null && length > 1 && length <= name.Length, "name must not be empty");
//
// Resolve N in N.R
//
MetadataMember left;
if (length == 2)
{
//
// If N is a single name, ignore functions: functions don't have members.
//
left = ResolveUnqualifiedName(name[0], true /* partOfQualifiedName */, errCtx);
}
else
{
left = ResolveFullyQualifiedName(name, length - 1, errCtx);
}
//
// Get R in N.R
//
string rightName = name[length - 1];
Debug.Assert(!String.IsNullOrEmpty(rightName), "rightName must not be empty");
//
// Resolve R in the context of N
//
return ResolveMetadataMemberAccess(left, rightName, errCtx);
}
private static Exception AmbiguousMetadataMemberName(ErrorContext errCtx, string name, MetadataNamespace ns1, MetadataNamespace ns2)
{
throw EntityUtil.EntitySqlError(errCtx, Strings.AmbiguousMetadataMemberName(name, ns1.Name, ns2 != null ? ns2.Name : null));
}
///
/// Try get type from the model using the fully qualified name.
///
private bool TryGetTypeFromMetadata(string typeFullName, out MetadataType type)
{
TypeUsage typeUsage;
if (_perspective.TryGetTypeByName(typeFullName, true /* ignore case */, out typeUsage))
{
type = new MetadataType(typeFullName, typeUsage);
return true;
}
else
{
type = null;
return false;
}
}
///
/// Try get function from the model using the fully qualified name.
///
internal bool TryGetFunctionFromMetadata(string functionFullName, out MetadataFunctionGroup functionGroup)
{
IList functionMetadata;
if (_perspective.TryGetFunctionByName(functionFullName, true /* ignore case */, out functionMetadata))
{
functionGroup = new MetadataFunctionGroup(functionFullName, functionMetadata);
return true;
}
else
{
functionGroup = null;
return false;
}
}
///
/// Try get function from the local metadata using the fully qualified name.
///
private bool TryGetInlineFunction(string functionName, out InlineFunctionGroup inlineFunctionGroup)
{
List inlineFunctionMetadata;
if (_includeInlineFunctions && _functionDefinitions.TryGetValue(functionName, out inlineFunctionMetadata))
{
inlineFunctionGroup = new InlineFunctionGroup(functionName, inlineFunctionMetadata);
return true;
}
else
{
inlineFunctionGroup = null;
return false;
}
}
///
/// Builds a dot-separated multipart identifier off the provided .
///
internal static string GetFullName(params string[] names)
{
Debug.Assert(names != null && names.Length > 0, "names must not be null or empty");
return String.Join(".", names);
}
}
}
// 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
- SamlAssertionKeyIdentifierClause.cs
- UserPersonalizationStateInfo.cs
- BrowserTree.cs
- TimeSpanSecondsOrInfiniteConverter.cs
- ProfileEventArgs.cs
- IssuedSecurityTokenProvider.cs
- Substitution.cs
- SqlServer2KCompatibilityAnnotation.cs
- XmlNamespaceMappingCollection.cs
- RepeatEnumerable.cs
- BitmapInitialize.cs
- mansign.cs
- KeyValueConfigurationCollection.cs
- HtmlTableCell.cs
- Blend.cs
- WebConfigurationHostFileChange.cs
- UriTemplateTable.cs
- PersonalizationStateInfoCollection.cs
- OdbcConnectionString.cs
- TextCollapsingProperties.cs
- SelectionListDesigner.cs
- RestClientProxyHandler.cs
- HostedImpersonationContext.cs
- ParsedAttributeCollection.cs
- ComplexPropertyEntry.cs
- NewExpression.cs
- DefaultPrintController.cs
- XsltSettings.cs
- AssemblyAttributes.cs
- ObjectContext.cs
- Rijndael.cs
- TextModifier.cs
- PropertyNames.cs
- _LazyAsyncResult.cs
- EditorAttributeInfo.cs
- CopyCodeAction.cs
- UnhandledExceptionEventArgs.cs
- ResXBuildProvider.cs
- VirtualizingStackPanel.cs
- ObjectTypeMapping.cs
- Triplet.cs
- IResourceProvider.cs
- AppSettingsSection.cs
- ColorPalette.cs
- DependencyObjectPropertyDescriptor.cs
- TransformedBitmap.cs
- Fonts.cs
- EdmPropertyAttribute.cs
- HostingEnvironmentException.cs
- RelationalExpressions.cs
- AsyncCompletedEventArgs.cs
- OleDbWrapper.cs
- FileIOPermission.cs
- glyphs.cs
- PathFigureCollection.cs
- TextStore.cs
- FontCollection.cs
- FileLevelControlBuilderAttribute.cs
- MenuEventArgs.cs
- FamilyMap.cs
- EntityUtil.cs
- NotConverter.cs
- ITreeGenerator.cs
- EdmConstants.cs
- DataControlExtensions.cs
- TransformerTypeCollection.cs
- MediaPlayerState.cs
- BuilderPropertyEntry.cs
- PassportAuthentication.cs
- SettingsSection.cs
- MouseGesture.cs
- ValidationErrorEventArgs.cs
- Helper.cs
- PrintControllerWithStatusDialog.cs
- SqlCacheDependencyDatabase.cs
- PackageRelationship.cs
- __Filters.cs
- WindowsHyperlink.cs
- TextTreeInsertElementUndoUnit.cs
- WorkflowInstanceExtensionProvider.cs
- Point3DAnimation.cs
- AppLevelCompilationSectionCache.cs
- CompressEmulationStream.cs
- Page.cs
- EntityDataReader.cs
- QilStrConcatenator.cs
- AppSettingsExpressionBuilder.cs
- SuppressMergeCheckAttribute.cs
- MetafileHeaderEmf.cs
- DocumentScope.cs
- RoleGroupCollection.cs
- ImmutableAssemblyCacheEntry.cs
- StatusBarPanel.cs
- SchemaImporterExtension.cs
- RightsManagementEncryptedStream.cs
- WebService.cs
- SecurityResources.cs
- ClientSession.cs
- EventNotify.cs
- SortDescriptionCollection.cs