Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / DataEntity / System / Data / Objects / ELinq / InitializerFacet.cs / 1305376 / InitializerFacet.cs
//---------------------------------------------------------------------- //// Copyright (c) Microsoft Corporation. All rights reserved. // // // @owner [....] //--------------------------------------------------------------------- using System.Data.Metadata.Edm; using System.Collections.Generic; using System.Linq.Expressions; using System.Reflection; using System.Diagnostics; using System.Linq; using System.Collections; using System.Data.Objects.DataClasses; using System.Threading; using System.Globalization; using System.Security.Permissions; using System.Security; using System.Data.Common.Internal.Materialization; using System.Data.Query.InternalTrees; using System.Text; using System.Data.Objects.Internal; namespace System.Data.Objects.ELinq { ////// Facet encapsulating information necessary to initialize a LINQ projection /// result. /// internal abstract class InitializerMetadata : IEquatable{ internal readonly Type ClrType; private static long s_identifier; internal readonly string Identity; private static readonly string s_identifierPrefix = typeof(InitializerMetadata).Name; private InitializerMetadata(Type clrType) { Debug.Assert(null != clrType); ClrType = clrType; Identity = s_identifierPrefix + Interlocked.Increment(ref s_identifier).ToString(CultureInfo.InvariantCulture); } // Gets the kind of this initializer (grouping, row, etc.) internal abstract InitializerMetadataKind Kind { get; } // Attempts to retrieve the initializer facet from a type usage internal static bool TryGetInitializerMetadata(TypeUsage typeUsage, out InitializerMetadata initializerMetadata) { initializerMetadata = null; if (BuiltInTypeKind.RowType == typeUsage.EdmType.BuiltInTypeKind) { initializerMetadata = ((RowType)typeUsage.EdmType).InitializerMetadata; } return null != initializerMetadata; } // Initializes an initializer for an IGrouping return type // Requires: resultType is IGrouping instance. internal static InitializerMetadata CreateGroupingInitializer(EdmItemCollection itemCollection, Type resultType) { return itemCollection.GetCanonicalInitializerMetadata(new GroupingInitializerMetadata(resultType)); } // Initializes an initializer for a MemberInit expression internal static InitializerMetadata CreateProjectionInitializer(EdmItemCollection itemCollection, MemberInitExpression initExpression, MemberInfo[] members) { return itemCollection.GetCanonicalInitializerMetadata(new ProjectionInitializerMetadata(initExpression, members)); } // Initializes an initializer for a New expression internal static InitializerMetadata CreateProjectionInitializer(EdmItemCollection itemCollection, NewExpression newExpression) { return itemCollection.GetCanonicalInitializerMetadata(new ProjectionNewMetadata(newExpression)); } // Initializes an initializer for a New expression with no properties internal static InitializerMetadata CreateEmptyProjectionInitializer(EdmItemCollection itemCollection, NewExpression newExpression) { return itemCollection.GetCanonicalInitializerMetadata(new EmptyProjectionNewMetadata(newExpression)); } // Creates metadata for entity collection materialization internal static InitializerMetadata CreateEntityCollectionInitializer(EdmItemCollection itemCollection, Type type, NavigationProperty navigationProperty) { return itemCollection.GetCanonicalInitializerMetadata(new EntityCollectionInitializerMetadata(type, navigationProperty)); } internal virtual void AppendColumnMapKey(ColumnMapKeyBuilder builder) { // by default, the type is sufficient (more information is needed for EntityCollection and initializers) builder.Append("CLR-", this.ClrType); } public override bool Equals(object obj) { Debug.Fail("use typed Equals method only"); return Equals(obj as InitializerMetadata); } public bool Equals(InitializerMetadata other) { Debug.Assert(null != other, "must not use a null key"); if (object.ReferenceEquals(this, other)) { return true; } if (this.Kind != other.Kind) { return false; } if (!this.ClrType.Equals(other.ClrType)) { return false; } return IsStructurallyEquivalent(other); } public override int GetHashCode() { return ClrType.GetHashCode(); } /// /// Requires: other has the same type as this and refers to the same CLR type /// Determine whether this Metadata is compatible with the other based on record layout. /// protected virtual bool IsStructurallyEquivalent(InitializerMetadata other) { return true; } ////// Produces an expression initializing an instance of ClrType (given emitters for input /// columns) /// internal abstract Expression Emit(Translator translator, ListpropertyTranslatorResults); /// /// Yields expected types for input columns. Null values are returned for children /// whose type is irrelevant to the initializer. /// internal abstract IEnumerableGetChildTypes(); /// /// return a list of propertyReader expressions from an array of translator results. /// /// ///protected static List GetPropertyReaders(List propertyTranslatorResults) { List propertyReaders = propertyTranslatorResults.Select(s => s.UnwrappedExpression).ToList(); return propertyReaders; } /// /// Implementation of IGrouping that can be initialized using the standard /// initializer pattern supported by ELinq /// ///Type of key ///Type of record private class Grouping: IGrouping { public Grouping(K key, IEnumerable group) { _key = key; _group = group; } private readonly K _key; private readonly IEnumerable _group; public K Key { get { return _key; } } public IEnumerable Group { get { return _group; } } IEnumerator IEnumerable .GetEnumerator() { if (null == _group) { yield break; } foreach (T member in _group) { yield return member; } } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return ((IEnumerable )this).GetEnumerator(); } } /// /// Metadata for grouping initializer. /// private class GroupingInitializerMetadata : InitializerMetadata { internal GroupingInitializerMetadata(Type type) : base(type) { } internal override InitializerMetadataKind Kind { get { return InitializerMetadataKind.Grouping; } } internal override Expression Emit(Translator translator, ListpropertyTranslatorResults) { // Create expression of the form: // new Grouping (children[0], children[1]) // Collect information... Debug.Assert(ClrType.IsGenericType && typeof(IGrouping<,>).Equals(ClrType.GetGenericTypeDefinition())); Debug.Assert(propertyTranslatorResults.Count == 2); Type keyType = this.ClrType.GetGenericArguments()[0]; Type groupElementType = this.ClrType.GetGenericArguments()[1]; Type groupType = typeof(Grouping<,>).MakeGenericType(keyType, groupElementType); ConstructorInfo constructor = groupType.GetConstructors().Single(); // new Grouping (children[0], children[1]) Expression newGrouping = Expression.Convert(Expression.New(constructor, GetPropertyReaders(propertyTranslatorResults)), this.ClrType); return newGrouping; } internal override IEnumerable GetChildTypes() { // Collect information... Debug.Assert(ClrType.IsGenericType && typeof(IGrouping<,>).Equals(ClrType.GetGenericTypeDefinition())); Type keyType = this.ClrType.GetGenericArguments()[0]; Type groupElementType = this.ClrType.GetGenericArguments()[1]; // key yield return keyType; // group yield return typeof(IEnumerable<>).MakeGenericType(groupElementType); } } /// /// Metadata for anonymous type materialization. /// private class ProjectionNewMetadata : InitializerMetadata { internal ProjectionNewMetadata(NewExpression newExpression) : base(newExpression.Type) { Debug.Assert(null != newExpression); _newExpression = newExpression; } private readonly NewExpression _newExpression; internal override InitializerMetadataKind Kind { get { return InitializerMetadataKind.ProjectionNew; } } protected override bool IsStructurallyEquivalent(InitializerMetadata other) { // caller must ensure the type matches ProjectionNewMetadata otherProjection = (ProjectionNewMetadata)other; if (this._newExpression.Members.Count != otherProjection._newExpression.Members.Count) { return false; } for (int i = 0; i < this._newExpression.Members.Count; i++) { MemberInfo thisMember = this._newExpression.Members[i]; MemberInfo otherMember = otherProjection._newExpression.Members[i]; if (!thisMember.Equals(otherMember)) { return false; } } return true; } internal override Expression Emit(Translator translator, ListpropertyTranslatorResults) { // Create expression of the form: // _newExpression(children) // (ClrType)null Expression nullProjection = Expression.Constant(null, this.ClrType); // _newExpression with members rebound Expression newProjection = Expression.New(_newExpression.Constructor, GetPropertyReaders(propertyTranslatorResults)); // _newExpression with members rebound to constants (used for security check) Expression constantProjection = Expression.New(_newExpression.Constructor, propertyTranslatorResults.Select(child => (Expression)Expression.Constant(TypeSystem.GetDefaultValue(child.UnwrappedExpression.Type), child.UnwrappedExpression.Type))); translator.RegisterUserExpression(constantProjection); // condition return newProjection; } internal override IEnumerable GetChildTypes() { // return all argument types return _newExpression.Arguments.Select(arg => arg.Type); } internal override void AppendColumnMapKey(ColumnMapKeyBuilder builder) { base.AppendColumnMapKey(builder); builder.Append(_newExpression.Constructor.ToString()); foreach (var member in _newExpression.Members ?? Enumerable.Empty ()) { builder.Append("DT", member.DeclaringType); builder.Append("." + member.Name); } } } private class EmptyProjectionNewMetadata : ProjectionNewMetadata { internal EmptyProjectionNewMetadata(NewExpression newExpression) : base(newExpression) { } internal override Expression Emit(Translator translator, List propertyReaders) { // ignore sentinel column return base.Emit(translator, new List ()); } internal override IEnumerable GetChildTypes() { // ignore sentinel column yield return null; } } /// /// Metadata for standard projection initializers. /// private class ProjectionInitializerMetadata : InitializerMetadata { internal ProjectionInitializerMetadata(MemberInitExpression initExpression, MemberInfo[] members) : base(initExpression.Type) { Debug.Assert(null != initExpression); Debug.Assert(null != members); _initExpression = initExpression; _members = members; } private readonly MemberInitExpression _initExpression; private readonly MemberInfo[] _members; internal override InitializerMetadataKind Kind { get { return InitializerMetadataKind.ProjectionInitializer; } } protected override bool IsStructurallyEquivalent(InitializerMetadata other) { // caller must ensure the type matches ProjectionInitializerMetadata otherProjection = (ProjectionInitializerMetadata)other; if (this._initExpression.Bindings.Count != otherProjection._initExpression.Bindings.Count) { return false; } for (int i = 0; i < this._initExpression.Bindings.Count; i++) { MemberBinding thisBinding = this._initExpression.Bindings[i]; MemberBinding otherBinding = otherProjection._initExpression.Bindings[i]; if (!thisBinding.Member.Equals(otherBinding.Member)) { return false; } } return true; } internal override Expression Emit(Translator translator, ListpropertyReaders) { // Create expression of the form: // _initExpression(children) // create member bindings (where values are taken from children) MemberBinding[] memberBindings = new MemberBinding[_initExpression.Bindings.Count]; MemberBinding[] constantMemberBindings = new MemberBinding[memberBindings.Length]; for (int i = 0; i < memberBindings.Length; i++) { MemberBinding originalBinding = _initExpression.Bindings[i]; Expression value = propertyReaders[i].UnwrappedExpression; MemberBinding newBinding = Expression.Bind(originalBinding.Member, value); MemberBinding constantBinding = Expression.Bind(originalBinding.Member, Expression.Constant( TypeSystem.GetDefaultValue(value.Type), value.Type)); memberBindings[i] = newBinding; constantMemberBindings[i] = constantBinding; } Expression newProjection = Expression.MemberInit(_initExpression.NewExpression, memberBindings); Expression constantProjection = Expression.MemberInit(_initExpression.NewExpression, constantMemberBindings); translator.RegisterUserExpression(constantProjection); return newProjection; } internal override IEnumerable GetChildTypes() { // return all argument types foreach (var binding in _initExpression.Bindings) { // determine member type Type memberType; string name; TypeSystem.PropertyOrField(binding.Member, out name, out memberType); yield return memberType; } } internal override void AppendColumnMapKey(ColumnMapKeyBuilder builder) { base.AppendColumnMapKey(builder); foreach (var binding in _initExpression.Bindings) { builder.Append(",", binding.Member.DeclaringType); builder.Append("." + binding.Member.Name); } } } /// /// Metadata for entity collection initializer. /// private class EntityCollectionInitializerMetadata : InitializerMetadata { internal EntityCollectionInitializerMetadata(Type type, NavigationProperty navigationProperty) : base(type) { Debug.Assert(null != navigationProperty); _navigationProperty = navigationProperty; } private readonly NavigationProperty _navigationProperty; internal override InitializerMetadataKind Kind { get { return InitializerMetadataKind.EntityCollection; } } ////// Make sure the other metadata instance generates the same property /// (otherwise, we get incorrect behavior where multiple nav props return /// the same type) /// protected override bool IsStructurallyEquivalent(InitializerMetadata other) { // caller must ensure the type matches EntityCollectionInitializerMetadata otherInitializer = (EntityCollectionInitializerMetadata)other; return this._navigationProperty.Equals(otherInitializer._navigationProperty); } private static readonly MethodInfo s_createEntityCollectionMethod = typeof(EntityCollectionInitializerMetadata).GetMethod("CreateEntityCollection", BindingFlags.Static | BindingFlags.Public); internal override Expression Emit(Translator translator, ListpropertyTranslatorResults) { Debug.Assert(propertyTranslatorResults.Count > 1, "no properties?"); Debug.Assert(propertyTranslatorResults[1] is CollectionTranslatorResult, "not a collection?"); Type elementType = GetElementType(); MethodInfo createEntityCollectionMethod = s_createEntityCollectionMethod.MakeGenericMethod(elementType); Expression shaper = Translator.Shaper_Parameter; Expression owner = propertyTranslatorResults[0].Expression; CollectionTranslatorResult collectionResult = propertyTranslatorResults[1] as CollectionTranslatorResult; Expression coordinator = collectionResult.ExpressionToGetCoordinator; // CreateEntityCollection(shaper, owner, elements, relationshipName, targetRoleName) Expression result = Expression.Call(createEntityCollectionMethod, shaper, owner, coordinator, Expression.Constant(_navigationProperty.RelationshipType.FullName), Expression.Constant(_navigationProperty.ToEndMember.Name)); return result; } public static EntityCollection CreateEntityCollection (Shaper state, IEntityWrapper wrappedOwner, Coordinator coordinator, string relationshipName, string targetRoleName) where T : class { if (null == wrappedOwner.Entity) { return null; } else { EntityCollection result = wrappedOwner.RelationshipManager.GetRelatedCollection (relationshipName, targetRoleName); // register a handler for deferred loading (when the nested result has been consumed) coordinator.RegisterCloseHandler((readerState, elements) => result.Load(elements, readerState.MergeOption)); return result; } } internal override IEnumerable GetChildTypes() { Type elementType = GetElementType(); yield return null; // defer in determining entity type... yield return typeof(IEnumerable<>).MakeGenericType(elementType); } internal override void AppendColumnMapKey(ColumnMapKeyBuilder builder) { base.AppendColumnMapKey(builder); builder.Append(",NP" + _navigationProperty.Name); builder.Append(",AT", _navigationProperty.DeclaringType); } private Type GetElementType() { // POCO support requires that we allow ICollection collections. This allows a POCO collection // to be projected in a LINQ query. Type elementType; if (!EntityUtil.TryGetICollectionElementType(ClrType, out elementType)) { throw EntityUtil.InvalidOperation(System.Data.Entity.Strings.ELinq_UnexpectedTypeForNavigationProperty( _navigationProperty, typeof(EntityCollection<>), typeof(ICollection<>), ClrType)); } return elementType; } } } internal enum InitializerMetadataKind { Grouping, ProjectionNew, ProjectionInitializer, EntityCollection, } } // 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
- TraceListener.cs
- EntityModelSchemaGenerator.cs
- HtmlSelect.cs
- StylusTouchDevice.cs
- Compiler.cs
- ColorConvertedBitmap.cs
- TableItemPatternIdentifiers.cs
- Image.cs
- HwndAppCommandInputProvider.cs
- CheckBoxList.cs
- XmlAttributeCollection.cs
- AnchoredBlock.cs
- DataTableCollection.cs
- SrgsRuleRef.cs
- SurrogateChar.cs
- TTSEngineProxy.cs
- MemoryResponseElement.cs
- BindingList.cs
- PeerMessageDispatcher.cs
- ServicePointManager.cs
- SiteMapProvider.cs
- CardSpaceSelector.cs
- FileSystemEventArgs.cs
- RsaKeyIdentifierClause.cs
- RTLAwareMessageBox.cs
- GeneralTransform2DTo3D.cs
- DockAndAnchorLayout.cs
- TreeNode.cs
- XmlC14NWriter.cs
- TypeSystemHelpers.cs
- glyphs.cs
- BindingManagerDataErrorEventArgs.cs
- RawUIStateInputReport.cs
- ByteAnimation.cs
- FormViewInsertEventArgs.cs
- AttachedPropertyBrowsableForTypeAttribute.cs
- HuffmanTree.cs
- SrgsSubset.cs
- BuildDependencySet.cs
- SqlProvider.cs
- ImagingCache.cs
- GridPatternIdentifiers.cs
- MouseBinding.cs
- XmlName.cs
- Content.cs
- Error.cs
- CodeRegionDirective.cs
- PreProcessInputEventArgs.cs
- DataSourceCache.cs
- ConditionedDesigner.cs
- SymLanguageType.cs
- XmlSchemaExporter.cs
- DataKeyArray.cs
- ISFClipboardData.cs
- PrincipalPermission.cs
- CodeIterationStatement.cs
- XmlSchemaSimpleTypeRestriction.cs
- DesignerSerializationOptionsAttribute.cs
- AdornerDecorator.cs
- QualificationDataItem.cs
- ManipulationLogic.cs
- JoinGraph.cs
- FocusManager.cs
- Visual.cs
- ReaderContextStackData.cs
- SimpleFileLog.cs
- ValueType.cs
- MetadataProperty.cs
- SoapCodeExporter.cs
- MergablePropertyAttribute.cs
- LineSegment.cs
- SoapObjectInfo.cs
- ExpressionBuilderContext.cs
- TrustManagerPromptUI.cs
- DateTimeSerializationSection.cs
- CounterSample.cs
- GradientStop.cs
- EventProvider.cs
- BufferBuilder.cs
- CompilerError.cs
- ParameterRetriever.cs
- ConstNode.cs
- DbConnectionPoolCounters.cs
- PersonalizationProviderCollection.cs
- Pool.cs
- HttpCookieCollection.cs
- ProjectionPath.cs
- CodeSubDirectory.cs
- OdbcUtils.cs
- PersistenceMetadataNamespace.cs
- ObjectStateFormatter.cs
- CodeTypeReferenceExpression.cs
- ContractUtils.cs
- DataBinding.cs
- HttpProtocolImporter.cs
- DbParameterHelper.cs
- WSTrustDec2005.cs
- CodeBlockBuilder.cs
- FamilyMapCollection.cs
- IResourceProvider.cs