Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / DataEntity / System / Data / Objects / Internal / EntityProxyTypeInfo.cs / 1305376 / EntityProxyTypeInfo.cs
//----------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// @owner [....]
// @backupOwner [....]
//---------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Linq;
using System.Reflection.Emit;
using System.Linq.Expressions;
using System.Data.Metadata.Edm;
using System.Data.Common.Utils;
namespace System.Data.Objects.Internal
{
///
/// Contains the Type of a proxy class, along with any behaviors associated with that proxy Type.
///
internal sealed class EntityProxyTypeInfo
{
private readonly Type _proxyType;
private readonly ClrEntityType _entityType; // The OSpace entity type that created this proxy info
internal const string EntityWrapperFieldName = "_entityWrapper";
private const string InitializeEntityCollectionsName = "InitializeEntityCollections";
private readonly FieldInfo _entityWrapperField;
private readonly DynamicMethod _initializeCollections;
private readonly Func _baseGetter;
private readonly HashSet _propertiesWithBaseGetter;
private readonly Action _baseSetter;
private readonly HashSet _propertiesWithBaseSetter;
private readonly Func Proxy_GetEntityWrapper;
private readonly Func _createObject;
// An index of relationship metadata strings to an AssociationType
// This is used when metadata is not otherwise available to the proxy
private readonly Dictionary, AssociationType> _navigationPropertyAssociationTypes;
internal EntityProxyTypeInfo(Type proxyType, ClrEntityType ospaceEntityType, DynamicMethod initializeCollections, List baseGetters, List baseSetters)
{
Debug.Assert(proxyType != null, "proxyType must be non-null");
_proxyType = proxyType;
_entityType = ospaceEntityType;
_initializeCollections = initializeCollections;
_navigationPropertyAssociationTypes = new Dictionary, AssociationType>();
foreach (NavigationProperty navigationProperty in ospaceEntityType.NavigationProperties)
{
_navigationPropertyAssociationTypes.Add(
new Tuple(
navigationProperty.RelationshipType.FullName,
navigationProperty.ToEndMember.Name),
(AssociationType)navigationProperty.RelationshipType);
if (navigationProperty.RelationshipType.Name != navigationProperty.RelationshipType.FullName)
{
// Sometimes there isn't enough metadata to have a container name
// Default codegen doesn't qualify names
_navigationPropertyAssociationTypes.Add(
new Tuple(
navigationProperty.RelationshipType.Name,
navigationProperty.ToEndMember.Name),
(AssociationType)navigationProperty.RelationshipType);
}
}
_entityWrapperField = proxyType.GetField(EntityWrapperFieldName, BindingFlags.DeclaredOnly | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
ParameterExpression Object_Parameter = Expression.Parameter(typeof(object), "proxy");
if (_entityWrapperField != null)
{
Expression> lambda = Expression.Lambda>(
Expression.Field(
Expression.Convert(Object_Parameter, _entityWrapperField.DeclaringType), _entityWrapperField),
Object_Parameter);
Func getEntityWrapperDelegate = lambda.Compile();
Proxy_GetEntityWrapper = (object proxy) =>
{
// This code validates that the wrapper points to the proxy that holds the wrapper.
// This guards against mischief by switching this wrapper out for another one obtained
// from a different object.
IEntityWrapper wrapper = ((IEntityWrapper)getEntityWrapperDelegate(proxy));
if (wrapper != null && !object.ReferenceEquals(wrapper.Entity, proxy))
{
throw new InvalidOperationException(System.Data.Entity.Strings.EntityProxyTypeInfo_ProxyHasWrongWrapper);
}
return wrapper;
};
}
ParameterExpression PropertyName_Parameter = Expression.Parameter(typeof(string), "propertyName");
MethodInfo baseGetterMethod = proxyType.GetMethod("GetBasePropertyValue", BindingFlags.Public | BindingFlags.Instance, null, new Type[] { typeof(string) }, null);
if (baseGetterMethod != null)
{
_baseGetter = Expression.Lambda>(
Expression.Call(Expression.Convert(Object_Parameter, proxyType), baseGetterMethod, PropertyName_Parameter),
Object_Parameter, PropertyName_Parameter).Compile();
}
ParameterExpression PropertyValue_Parameter = Expression.Parameter(typeof(object), "propertyName");
MethodInfo baseSetterMethod = proxyType.GetMethod("SetBasePropertyValue", BindingFlags.Public | BindingFlags.Instance, null, new Type[] { typeof(string), typeof(object) }, null);
if (baseSetterMethod != null)
{
_baseSetter = Expression.Lambda>(
Expression.Call(Expression.Convert(Object_Parameter, proxyType), baseSetterMethod, PropertyName_Parameter, PropertyValue_Parameter),
Object_Parameter, PropertyName_Parameter, PropertyValue_Parameter).Compile();
}
_propertiesWithBaseGetter = new HashSet(baseGetters.Select(p => p.Name));
_propertiesWithBaseSetter = new HashSet(baseSetters.Select(p => p.Name));
_createObject = LightweightCodeGenerator.CreateConstructor(proxyType) as Func;
}
internal object CreateProxyObject()
{
return _createObject();
}
internal Type ProxyType
{
get { return _proxyType; }
}
internal DynamicMethod InitializeEntityCollections
{
get { return _initializeCollections; }
}
public Func BaseGetter
{
get { return _baseGetter; }
}
public bool ContainsBaseGetter(string propertyName)
{
return BaseGetter != null && _propertiesWithBaseGetter.Contains(propertyName);
}
public bool ContainsBaseSetter(string propertyName)
{
return BaseSetter != null && _propertiesWithBaseSetter.Contains(propertyName);
}
public Action BaseSetter
{
get { return _baseSetter; }
}
public bool TryGetNavigationPropertyAssociationType(string relationshipName, string targetRoleName, out AssociationType associationType)
{
return _navigationPropertyAssociationTypes.TryGetValue(new Tuple(relationshipName, targetRoleName), out associationType);
}
public void ValidateType(ClrEntityType ospaceEntityType)
{
if (ospaceEntityType != _entityType && ospaceEntityType.HashedDescription != _entityType.HashedDescription)
{
Debug.Assert(ospaceEntityType.ClrType == _entityType.ClrType);
throw EntityUtil.DuplicateTypeForProxyType(ospaceEntityType.ClrType);
}
}
#region Wrapper on the Proxy
///
/// Set the proxy object's private entity wrapper field value to the specified entity wrapper object.
/// The proxy object (representing the wrapped entity) is retrieved from the wrapper itself.
///
/// Wrapper object to be referenced by the proxy.
///
/// The supplied entity wrapper.
/// This is done so that this method can be more easily composed within lambda expressions (such as in the materializer).
///
internal IEntityWrapper SetEntityWrapper(IEntityWrapper wrapper)
{
Debug.Assert(wrapper != null, "wrapper must be non-null");
Debug.Assert(wrapper.Entity != null, "proxy must be non-null");
if (_entityWrapperField != null)
{
Debug.Assert(_entityWrapperField.DeclaringType.IsAssignableFrom(wrapper.Entity.GetType()), "proxy is not of the correct Type");
_entityWrapperField.SetValue(wrapper.Entity, wrapper);
}
return wrapper;
}
///
/// Gets the proxy object's entity wrapper field value
///
///
///
internal IEntityWrapper GetEntityWrapper(object entity)
{
return Proxy_GetEntityWrapper(entity) as IEntityWrapper;
}
internal Func EntityWrapperDelegate
{
get { return Proxy_GetEntityWrapper; }
}
#endregion
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//----------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// @owner [....]
// @backupOwner [....]
//---------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Linq;
using System.Reflection.Emit;
using System.Linq.Expressions;
using System.Data.Metadata.Edm;
using System.Data.Common.Utils;
namespace System.Data.Objects.Internal
{
///
/// Contains the Type of a proxy class, along with any behaviors associated with that proxy Type.
///
internal sealed class EntityProxyTypeInfo
{
private readonly Type _proxyType;
private readonly ClrEntityType _entityType; // The OSpace entity type that created this proxy info
internal const string EntityWrapperFieldName = "_entityWrapper";
private const string InitializeEntityCollectionsName = "InitializeEntityCollections";
private readonly FieldInfo _entityWrapperField;
private readonly DynamicMethod _initializeCollections;
private readonly Func _baseGetter;
private readonly HashSet _propertiesWithBaseGetter;
private readonly Action _baseSetter;
private readonly HashSet _propertiesWithBaseSetter;
private readonly Func Proxy_GetEntityWrapper;
private readonly Func _createObject;
// An index of relationship metadata strings to an AssociationType
// This is used when metadata is not otherwise available to the proxy
private readonly Dictionary, AssociationType> _navigationPropertyAssociationTypes;
internal EntityProxyTypeInfo(Type proxyType, ClrEntityType ospaceEntityType, DynamicMethod initializeCollections, List baseGetters, List baseSetters)
{
Debug.Assert(proxyType != null, "proxyType must be non-null");
_proxyType = proxyType;
_entityType = ospaceEntityType;
_initializeCollections = initializeCollections;
_navigationPropertyAssociationTypes = new Dictionary, AssociationType>();
foreach (NavigationProperty navigationProperty in ospaceEntityType.NavigationProperties)
{
_navigationPropertyAssociationTypes.Add(
new Tuple(
navigationProperty.RelationshipType.FullName,
navigationProperty.ToEndMember.Name),
(AssociationType)navigationProperty.RelationshipType);
if (navigationProperty.RelationshipType.Name != navigationProperty.RelationshipType.FullName)
{
// Sometimes there isn't enough metadata to have a container name
// Default codegen doesn't qualify names
_navigationPropertyAssociationTypes.Add(
new Tuple(
navigationProperty.RelationshipType.Name,
navigationProperty.ToEndMember.Name),
(AssociationType)navigationProperty.RelationshipType);
}
}
_entityWrapperField = proxyType.GetField(EntityWrapperFieldName, BindingFlags.DeclaredOnly | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
ParameterExpression Object_Parameter = Expression.Parameter(typeof(object), "proxy");
if (_entityWrapperField != null)
{
Expression> lambda = Expression.Lambda>(
Expression.Field(
Expression.Convert(Object_Parameter, _entityWrapperField.DeclaringType), _entityWrapperField),
Object_Parameter);
Func getEntityWrapperDelegate = lambda.Compile();
Proxy_GetEntityWrapper = (object proxy) =>
{
// This code validates that the wrapper points to the proxy that holds the wrapper.
// This guards against mischief by switching this wrapper out for another one obtained
// from a different object.
IEntityWrapper wrapper = ((IEntityWrapper)getEntityWrapperDelegate(proxy));
if (wrapper != null && !object.ReferenceEquals(wrapper.Entity, proxy))
{
throw new InvalidOperationException(System.Data.Entity.Strings.EntityProxyTypeInfo_ProxyHasWrongWrapper);
}
return wrapper;
};
}
ParameterExpression PropertyName_Parameter = Expression.Parameter(typeof(string), "propertyName");
MethodInfo baseGetterMethod = proxyType.GetMethod("GetBasePropertyValue", BindingFlags.Public | BindingFlags.Instance, null, new Type[] { typeof(string) }, null);
if (baseGetterMethod != null)
{
_baseGetter = Expression.Lambda>(
Expression.Call(Expression.Convert(Object_Parameter, proxyType), baseGetterMethod, PropertyName_Parameter),
Object_Parameter, PropertyName_Parameter).Compile();
}
ParameterExpression PropertyValue_Parameter = Expression.Parameter(typeof(object), "propertyName");
MethodInfo baseSetterMethod = proxyType.GetMethod("SetBasePropertyValue", BindingFlags.Public | BindingFlags.Instance, null, new Type[] { typeof(string), typeof(object) }, null);
if (baseSetterMethod != null)
{
_baseSetter = Expression.Lambda>(
Expression.Call(Expression.Convert(Object_Parameter, proxyType), baseSetterMethod, PropertyName_Parameter, PropertyValue_Parameter),
Object_Parameter, PropertyName_Parameter, PropertyValue_Parameter).Compile();
}
_propertiesWithBaseGetter = new HashSet(baseGetters.Select(p => p.Name));
_propertiesWithBaseSetter = new HashSet(baseSetters.Select(p => p.Name));
_createObject = LightweightCodeGenerator.CreateConstructor(proxyType) as Func;
}
internal object CreateProxyObject()
{
return _createObject();
}
internal Type ProxyType
{
get { return _proxyType; }
}
internal DynamicMethod InitializeEntityCollections
{
get { return _initializeCollections; }
}
public Func BaseGetter
{
get { return _baseGetter; }
}
public bool ContainsBaseGetter(string propertyName)
{
return BaseGetter != null && _propertiesWithBaseGetter.Contains(propertyName);
}
public bool ContainsBaseSetter(string propertyName)
{
return BaseSetter != null && _propertiesWithBaseSetter.Contains(propertyName);
}
public Action BaseSetter
{
get { return _baseSetter; }
}
public bool TryGetNavigationPropertyAssociationType(string relationshipName, string targetRoleName, out AssociationType associationType)
{
return _navigationPropertyAssociationTypes.TryGetValue(new Tuple(relationshipName, targetRoleName), out associationType);
}
public void ValidateType(ClrEntityType ospaceEntityType)
{
if (ospaceEntityType != _entityType && ospaceEntityType.HashedDescription != _entityType.HashedDescription)
{
Debug.Assert(ospaceEntityType.ClrType == _entityType.ClrType);
throw EntityUtil.DuplicateTypeForProxyType(ospaceEntityType.ClrType);
}
}
#region Wrapper on the Proxy
///
/// Set the proxy object's private entity wrapper field value to the specified entity wrapper object.
/// The proxy object (representing the wrapped entity) is retrieved from the wrapper itself.
///
/// Wrapper object to be referenced by the proxy.
///
/// The supplied entity wrapper.
/// This is done so that this method can be more easily composed within lambda expressions (such as in the materializer).
///
internal IEntityWrapper SetEntityWrapper(IEntityWrapper wrapper)
{
Debug.Assert(wrapper != null, "wrapper must be non-null");
Debug.Assert(wrapper.Entity != null, "proxy must be non-null");
if (_entityWrapperField != null)
{
Debug.Assert(_entityWrapperField.DeclaringType.IsAssignableFrom(wrapper.Entity.GetType()), "proxy is not of the correct Type");
_entityWrapperField.SetValue(wrapper.Entity, wrapper);
}
return wrapper;
}
///
/// Gets the proxy object's entity wrapper field value
///
///
///
internal IEntityWrapper GetEntityWrapper(object entity)
{
return Proxy_GetEntityWrapper(entity) as IEntityWrapper;
}
internal Func EntityWrapperDelegate
{
get { return Proxy_GetEntityWrapper; }
}
#endregion
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.