Code:
/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / Orcas / SP / ndp / fx / src / DataEntity / System / Data / Objects / ELinq / InitializerFacet.cs / 3 / 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; 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.Expression).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.Expression.Type), child.Expression.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].Expression; 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, IEntityWithRelationships owner, Coordinator coordinator, string relationshipName, string targetRoleName) where T : class, IEntityWithRelationships { if (null == owner) { return null; } else { EntityCollection result = owner.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() { if (!this.ClrType.IsGenericType || !typeof(EntityCollection<>).Equals(ClrType.GetGenericTypeDefinition())) { throw EntityUtil.InvalidOperation(System.Data.Entity.Strings.ELinq_UnexpectedTypeForNavigationProperty( _navigationProperty, typeof(EntityCollection<>), ClrType)); } Type elementType = this.ClrType.GetGenericArguments()[0]; return elementType; } } } internal enum InitializerMetadataKind { Grouping, ProjectionNew, ProjectionInitializer, EntityCollection, } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. //---------------------------------------------------------------------- // // 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; 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.Expression).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.Expression.Type), child.Expression.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].Expression; 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, IEntityWithRelationships owner, Coordinator coordinator, string relationshipName, string targetRoleName) where T : class, IEntityWithRelationships { if (null == owner) { return null; } else { EntityCollection result = owner.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() { if (!this.ClrType.IsGenericType || !typeof(EntityCollection<>).Equals(ClrType.GetGenericTypeDefinition())) { throw EntityUtil.InvalidOperation(System.Data.Entity.Strings.ELinq_UnexpectedTypeForNavigationProperty( _navigationProperty, typeof(EntityCollection<>), ClrType)); } Type elementType = this.ClrType.GetGenericArguments()[0]; 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
- StringArrayConverter.cs
- SelectQueryOperator.cs
- PerfCounterSection.cs
- Events.cs
- ISFTagAndGuidCache.cs
- Part.cs
- XmlIlVisitor.cs
- WorkflowViewElement.cs
- DbConnectionPoolCounters.cs
- SamlSecurityTokenAuthenticator.cs
- ActivityCodeDomReferenceService.cs
- AmbientProperties.cs
- Action.cs
- RIPEMD160.cs
- ProjectionPlan.cs
- ImageBrush.cs
- FileDialog_Vista_Interop.cs
- InputLangChangeEvent.cs
- PathFigureCollectionValueSerializer.cs
- XmlNodeChangedEventArgs.cs
- MediaPlayer.cs
- TableLayoutPanelCellPosition.cs
- CaseStatementSlot.cs
- externdll.cs
- OperationFormatter.cs
- PerformanceCounterPermissionEntry.cs
- RecordBuilder.cs
- Visitors.cs
- ProvidePropertyAttribute.cs
- WebAdminConfigurationHelper.cs
- PeerPresenceInfo.cs
- PackageRelationshipCollection.cs
- XmlBinaryReader.cs
- TreeNodeBinding.cs
- WindowShowOrOpenTracker.cs
- EncoderFallback.cs
- TableParagraph.cs
- SqlTransaction.cs
- FormViewDeleteEventArgs.cs
- WebControlsSection.cs
- TextRunTypographyProperties.cs
- MSAANativeProvider.cs
- BackgroundWorker.cs
- DetailsViewInsertedEventArgs.cs
- KeyboardNavigation.cs
- SettingsPropertyCollection.cs
- DocumentPageTextView.cs
- StorageAssociationSetMapping.cs
- VisualStateManager.cs
- NetTcpSecurityElement.cs
- DebugView.cs
- OdbcStatementHandle.cs
- EventlogProvider.cs
- SqlDataSourceCache.cs
- DetailsViewRowCollection.cs
- Int32RectConverter.cs
- ScriptMethodAttribute.cs
- X509UI.cs
- RuntimeConfigLKG.cs
- ValidationHelper.cs
- WindowsGraphicsCacheManager.cs
- SecurityState.cs
- SortableBindingList.cs
- dbdatarecord.cs
- FixedStringLookup.cs
- XmlUtilWriter.cs
- PropertyCollection.cs
- ChildChangedEventArgs.cs
- InheritablePropertyChangeInfo.cs
- LayoutEditorPart.cs
- Internal.cs
- XmlSerializerOperationBehavior.cs
- StylusDownEventArgs.cs
- ResourceProviderFactory.cs
- AsymmetricSignatureFormatter.cs
- TextRunCacheImp.cs
- WmfPlaceableFileHeader.cs
- RegexGroup.cs
- DesignerHierarchicalDataSourceView.cs
- CurrencyManager.cs
- ComponentCollection.cs
- ContainerUtilities.cs
- NonClientArea.cs
- WindowsHyperlink.cs
- FrameworkEventSource.cs
- RegexGroupCollection.cs
- MsmqReceiveHelper.cs
- XmlSerializer.cs
- ByteStorage.cs
- DocobjHost.cs
- ClickablePoint.cs
- ResourcePart.cs
- HtmlGenericControl.cs
- EntityDataSourceStatementEditorForm.cs
- XmlSerializerFactory.cs
- AuthenticationConfig.cs
- dataprotectionpermissionattribute.cs
- MeasureItemEvent.cs
- WebPartDisplayModeCancelEventArgs.cs
- HScrollBar.cs