Code:
/ Dotnetfx_Vista_SP2 / Dotnetfx_Vista_SP2 / 8.0.50727.4016 / DEVDIV / depot / DevDiv / releases / Orcas / QFE / ndp / fx / src / DataEntity / System / Data / Objects / ELinq / InitializerFacet.cs / 2 / 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, List propertyTranslatorResults);
///
/// Yields expected types for input columns. Null values are returned for children
/// whose type is irrelevant to the initializer.
///
internal abstract IEnumerable GetChildTypes();
///
/// 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, List propertyTranslatorResults)
{
// 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, List propertyTranslatorResults)
{
// 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, List propertyReaders)
{
// 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, List propertyTranslatorResults)
{
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, List propertyTranslatorResults);
///
/// Yields expected types for input columns. Null values are returned for children
/// whose type is irrelevant to the initializer.
///
internal abstract IEnumerable GetChildTypes();
///
/// 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, List propertyTranslatorResults)
{
// 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, List propertyTranslatorResults)
{
// 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, List propertyReaders)
{
// 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, List propertyTranslatorResults)
{
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
- TimeIntervalCollection.cs
- AssemblyResourceLoader.cs
- CombinedGeometry.cs
- StructuralObject.cs
- DataGridViewRowCancelEventArgs.cs
- HtmlGenericControl.cs
- ArrayHelper.cs
- BinaryFormatter.cs
- BindingExpressionBase.cs
- ConfigurationManager.cs
- SafeWaitHandle.cs
- XmlDictionaryString.cs
- CompositeFontParser.cs
- AuthenticationModeHelper.cs
- TypeDescriptor.cs
- DBDataPermission.cs
- ConfigurationPropertyCollection.cs
- InvalidateEvent.cs
- DataControlReference.cs
- sqlpipe.cs
- DateTimeAutomationPeer.cs
- Sql8ConformanceChecker.cs
- NotificationContext.cs
- FlowDocumentReader.cs
- BulletDecorator.cs
- ServiceRoute.cs
- PackageFilter.cs
- Control.cs
- KeyValueInternalCollection.cs
- GeometryHitTestParameters.cs
- AccessedThroughPropertyAttribute.cs
- OledbConnectionStringbuilder.cs
- BinaryMessageEncodingBindingElement.cs
- TdsParameterSetter.cs
- ConfigurationLoaderException.cs
- PathTooLongException.cs
- SqlUdtInfo.cs
- ServiceModelStringsVersion1.cs
- ByteAnimationUsingKeyFrames.cs
- WindowsListViewItemCheckBox.cs
- _ProxyChain.cs
- DataGridViewUtilities.cs
- XsdValidatingReader.cs
- HtmlTitle.cs
- NavigationHelper.cs
- ListenerElementsCollection.cs
- UpdateTranslator.cs
- DataGridDetailsPresenterAutomationPeer.cs
- FrameSecurityDescriptor.cs
- XmlCharCheckingReader.cs
- CollectionViewSource.cs
- CodeCompiler.cs
- TextElementEnumerator.cs
- XamlDesignerSerializationManager.cs
- X509Certificate2.cs
- TraceInternal.cs
- TextSerializer.cs
- ProtocolsConfigurationHandler.cs
- CompensationTokenData.cs
- StackSpiller.cs
- SecurityDescriptor.cs
- AccessViolationException.cs
- mediaeventshelper.cs
- XPathMultyIterator.cs
- IntellisenseTextBox.designer.cs
- Parser.cs
- WebPartDisplayMode.cs
- RecognizeCompletedEventArgs.cs
- MasterPageCodeDomTreeGenerator.cs
- PKCS1MaskGenerationMethod.cs
- HTTPNotFoundHandler.cs
- NamedPipeAppDomainProtocolHandler.cs
- ProofTokenCryptoHandle.cs
- TemplateXamlTreeBuilder.cs
- MembershipPasswordException.cs
- Assembly.cs
- GlyphCache.cs
- MsmqProcessProtocolHandler.cs
- StatusBar.cs
- SqlDataSourceAdvancedOptionsForm.cs
- XmlAttributes.cs
- PerformanceCounterLib.cs
- CredentialCache.cs
- DataSourceSelectArguments.cs
- CompositeDataBoundControl.cs
- TagPrefixCollection.cs
- VectorAnimationUsingKeyFrames.cs
- webeventbuffer.cs
- DataGrid.cs
- OdbcEnvironmentHandle.cs
- UInt32Converter.cs
- ProviderIncompatibleException.cs
- HyperLinkColumn.cs
- PersonalizationStateInfo.cs
- ConnectionStringsExpressionBuilder.cs
- SchemaDeclBase.cs
- CodeTypeDelegate.cs
- Enlistment.cs
- ContentDisposition.cs
- ActivityBindForm.Designer.cs