private static EntityProxyTypeInfo BuildType( ModuleBuilder moduleBuilder, ClrEntityType ospaceEntityType, MetadataWorkspace workspace) { EntityProxyFactory.ProxyTypeBuilder proxyTypeBuilder = new EntityProxyFactory.ProxyTypeBuilder(ospaceEntityType); Type type = proxyTypeBuilder.CreateType(moduleBuilder); EntityProxyTypeInfo proxyTypeInfo; if (type != (Type)null) { Assembly assembly = type.Assembly(); if (!EntityProxyFactory._proxyRuntimeAssemblies.Contains(assembly)) { EntityProxyFactory._proxyRuntimeAssemblies.Add(assembly); EntityProxyFactory.AddAssemblyToResolveList(assembly); } proxyTypeInfo = new EntityProxyTypeInfo(type, ospaceEntityType, proxyTypeBuilder.CreateInitalizeCollectionMethod(type), proxyTypeBuilder.BaseGetters, proxyTypeBuilder.BaseSetters, workspace); foreach (EdmMember lazyLoadMember in proxyTypeBuilder.LazyLoadMembers) { EntityProxyFactory.InterceptMember(lazyLoadMember, type, proxyTypeInfo); } EntityProxyFactory.SetResetFKSetterFlagDelegate(type, proxyTypeInfo); EntityProxyFactory.SetCompareByteArraysDelegate(type); } else { proxyTypeInfo = (EntityProxyTypeInfo)null; } return(proxyTypeInfo); }
// <summary> // Return proxy type information for the specified O-Space EntityType. // </summary> // <param name="ospaceEntityType"> EntityType in O-Space that represents the CLR type to be proxied. Must not be null. </param> // <returns> A non-null EntityProxyTypeInfo instance that contains information about the type of proxy for the specified O-Space EntityType; or null if no proxy can be created for the specified type. </returns> internal static EntityProxyTypeInfo GetProxyType(ClrEntityType ospaceEntityType, MetadataWorkspace workspace) { DebugCheck.NotNull(ospaceEntityType); DebugCheck.NotNull(workspace); Debug.Assert(ospaceEntityType.DataSpace == DataSpace.OSpace, "ospaceEntityType.DataSpace must be OSpace"); EntityProxyTypeInfo proxyTypeInfo = null; // Check if an entry for the proxy type already exists. if (TryGetProxyType(ospaceEntityType.ClrType, ospaceEntityType.CSpaceTypeName, out proxyTypeInfo)) { if (proxyTypeInfo != null) { proxyTypeInfo.ValidateType(ospaceEntityType); } return(proxyTypeInfo); } // No entry found, may need to create one. // Acquire an upgradeable read lock so that: // 1. Other readers aren't blocked while the second existence check is performed. // 2. Other threads that may have also detected the absence of an entry block while the first thread handles proxy type creation. _typeMapLock.EnterUpgradeableReadLock(); try { return(TryCreateProxyType(ospaceEntityType, workspace)); } finally { _typeMapLock.ExitUpgradeableReadLock(); } }
// <summary> // Construct an interception delegate for the specified proxy member. // </summary> // <param name="member"> EdmMember that specifies the member to be intercepted. </param> // <param name="proxyType"> Type of the proxy. </param> private static void InterceptMember(EdmMember member, Type proxyType, EntityProxyTypeInfo proxyTypeInfo) { var property = proxyType.GetTopProperty(member.Name); Debug.Assert( property != null, String.Format( CultureInfo.CurrentCulture, "Expected property {0} to be defined on proxy type {1}", member.Name, proxyType.FullName)); var interceptorField = proxyType.GetField( LazyLoadImplementor.GetInterceptorFieldName(member.Name), BindingFlags.DeclaredOnly | BindingFlags.Static | BindingFlags.NonPublic); Debug.Assert( interceptorField != null, String.Format( CultureInfo.CurrentCulture, "Expected interceptor field for property {0} to be defined on proxy type {1}", member.Name, proxyType.FullName)); var interceptorDelegate = GetInterceptorDelegateMethod. MakeGenericMethod(proxyType, property.PropertyType). Invoke(null, new object[] { member, proxyTypeInfo.EntityWrapperDelegate }) as Delegate; AssignInterceptionDelegate(interceptorDelegate, interceptorField); }
private static void SetResetFKSetterFlagDelegate( Type proxyType, EntityProxyTypeInfo proxyTypeInfo) { FieldInfo field = proxyType.GetField("_resetFKSetterFlag", BindingFlags.DeclaredOnly | BindingFlags.Static | BindingFlags.NonPublic); EntityProxyFactory.AssignInterceptionDelegate((Delegate)EntityProxyFactory.GetResetFKSetterFlagDelegate(proxyTypeInfo.EntityWrapperDelegate), field); }
/// <summary> /// A mechanism to lookup AssociationType metadata for proxies for a given entity and association information /// </summary> /// <param name="wrappedEntity"> The entity instance used to lookup the proxy type </param> /// <param name="relationshipName"> The name of the relationship (FullName or Name) </param> /// <param name="targetRoleName"> Target role of the relationship </param> /// <param name="associationType"> The AssociationType for that property </param> /// <returns> True if an AssociationType is found in proxy metadata, false otherwise </returns> internal static bool TryGetAssociationTypeFromProxyInfo( IEntityWrapper wrappedEntity, string relationshipName, string targetRoleName, out AssociationType associationType) { EntityProxyTypeInfo proxyInfo = null; associationType = null; return(TryGetProxyType(wrappedEntity.Entity.GetType(), out proxyInfo) && proxyInfo != null && proxyInfo.TryGetNavigationPropertyAssociationType(relationshipName, targetRoleName, out associationType)); }
public void GetAllRelationshipsForType_returns_collection_relationships_with_navigation_properties() { using (var context = new RelationshipsContext()) { var relationships = EntityProxyTypeInfo.GetAllRelationshipsForType( ((IObjectContextAdapter)context).ObjectContext.MetadataWorkspace, typeof(OneToMany)) .Select(r => r.Name); Assert.Equal("OneToMany_WithNavProps", relationships.Single()); } }
// <summary> // Sets a delegate onto the _resetFKSetterFlag field such that it can be executed to make // a call into the state manager to reset the InFKSetter flag. // </summary> private static void SetResetFKSetterFlagDelegate(Type proxyType, EntityProxyTypeInfo proxyTypeInfo) { var resetFKSetterFlagField = proxyType.GetField( ResetFKSetterFlagFieldName, BindingFlags.DeclaredOnly | BindingFlags.Static | BindingFlags.NonPublic); Debug.Assert(resetFKSetterFlagField != null, "Expected resetFKSetterFlagField to be defined on the proxy type."); var resetFKSetterFlagDelegate = GetResetFKSetterFlagDelegate(proxyTypeInfo.EntityWrapperDelegate); AssignInterceptionDelegate(resetFKSetterFlagDelegate, resetFKSetterFlagField); }
internal static bool TryGetProxyType(Type proxyType, out EntityProxyTypeInfo proxyTypeInfo) { _typeMapLock.EnterReadLock(); try { return(_proxyTypeMap.TryGetValue(proxyType, out proxyTypeInfo)); } finally { _typeMapLock.ExitReadLock(); } }
internal static bool TryGetProxyType(Type clrType, string entityTypeName, out EntityProxyTypeInfo proxyTypeInfo) { _typeMapLock.EnterReadLock(); try { return(_proxyNameMap.TryGetValue(new Tuple <Type, string>(clrType, entityTypeName), out proxyTypeInfo)); } finally { _typeMapLock.ExitReadLock(); } }
internal EntityProxyTypeInfo( Type proxyType, ClrEntityType ospaceEntityType, DynamicMethod initializeCollections, List <PropertyInfo> baseGetters, List <PropertyInfo> baseSetters, MetadataWorkspace workspace) { this._proxyType = proxyType; this._entityType = ospaceEntityType; this._initializeCollections = initializeCollections; foreach (AssociationType associationType in EntityProxyTypeInfo.GetAllRelationshipsForType(workspace, proxyType)) { this._navigationPropertyAssociationTypes.Add(associationType.FullName, associationType); if (associationType.Name != associationType.FullName) { this._navigationPropertyAssociationTypes.Add(associationType.Name, associationType); } } FieldInfo field = proxyType.GetField("_entityWrapper", BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); ParameterExpression parameterExpression4 = Expression.Parameter(typeof(object), "proxy"); ParameterExpression parameterExpression5 = Expression.Parameter(typeof(object), "value"); Func <object, object> getEntityWrapperDelegate = Expression.Lambda <Func <object, object> >((Expression)Expression.Field((Expression)Expression.Convert((Expression)parameterExpression4, field.DeclaringType), field), parameterExpression4).Compile(); this.Proxy_GetEntityWrapper = (Func <object, object>)(proxy => { IEntityWrapper entityWrapper = (IEntityWrapper)getEntityWrapperDelegate(proxy); if (entityWrapper != null && !object.ReferenceEquals(entityWrapper.Entity, proxy)) { throw new InvalidOperationException(Strings.EntityProxyTypeInfo_ProxyHasWrongWrapper); } return((object)entityWrapper); }); this.Proxy_SetEntityWrapper = ((Expression <Func <object, object, object> >)((parameterExpression1, parameterExpression2) => Expression.Assign((Expression)Expression.Field((Expression)Expression.Convert((Expression)parameterExpression4, field.DeclaringType), field), parameterExpression2))).Compile(); ParameterExpression parameterExpression6 = Expression.Parameter(typeof(string), "propertyName"); MethodInfo publicInstanceMethod1 = proxyType.GetPublicInstanceMethod("GetBasePropertyValue", typeof(string)); if (publicInstanceMethod1 != (MethodInfo)null) { this._baseGetter = Expression.Lambda <Func <object, string, object> >((Expression)Expression.Call((Expression)Expression.Convert((Expression)parameterExpression4, proxyType), publicInstanceMethod1, (Expression)parameterExpression6), parameterExpression4, parameterExpression6).Compile(); } ParameterExpression parameterExpression7 = Expression.Parameter(typeof(object), "propertyName"); MethodInfo publicInstanceMethod2 = proxyType.GetPublicInstanceMethod("SetBasePropertyValue", typeof(string), typeof(object)); if (publicInstanceMethod2 != (MethodInfo)null) { this._baseSetter = ((Expression <Action <object, string, object> >)((parameterExpression1, parameterExpression2, parameterExpression3) => Expression.Call((Expression)Expression.Convert(parameterExpression1, proxyType), publicInstanceMethod2, parameterExpression2, parameterExpression3))).Compile(); } this._propertiesWithBaseGetter = new HashSet <string>(baseGetters.Select <PropertyInfo, string>((Func <PropertyInfo, string>)(p => p.Name))); this._propertiesWithBaseSetter = new HashSet <string>(baseSetters.Select <PropertyInfo, string>((Func <PropertyInfo, string>)(p => p.Name))); this._createObject = DelegateFactory.CreateConstructor(proxyType); }
public void GetAllRelationshipsForType_returns_relationships_without_navigation_properties() { using (var context = new RelationshipsContext()) { var relationships = EntityProxyTypeInfo.GetAllRelationshipsForType( ((IObjectContextAdapter)context).ObjectContext.MetadataWorkspace, typeof(NoNavProps)) .Select(r => r.Name); Assert.Equal(2, relationships.Count()); Assert.Contains("NoNavPropsOneToOne_NoNavProps", relationships); Assert.Contains("NoNavPropsOneToMany_NoNavProps", relationships); } }
internal static IEnumerable <AssociationType> GetAllRelationshipsForType( MetadataWorkspace workspace, Type clrType) { return(workspace.GetItemCollection(DataSpace.OSpace).GetItems <AssociationType>().Where <AssociationType>((Func <AssociationType, bool>)(a => { if (!EntityProxyTypeInfo.IsEndMemberForType(a.AssociationEndMembers[0], clrType)) { return EntityProxyTypeInfo.IsEndMemberForType(a.AssociationEndMembers[1], clrType); } return true; }))); }
private static void InterceptMember( EdmMember member, Type proxyType, EntityProxyTypeInfo proxyTypeInfo) { PropertyInfo topProperty = proxyType.GetTopProperty(member.Name); FieldInfo field = proxyType.GetField(LazyLoadImplementor.GetInterceptorFieldName(member.Name), BindingFlags.DeclaredOnly | BindingFlags.Static | BindingFlags.NonPublic); EntityProxyFactory.AssignInterceptionDelegate(EntityProxyFactory.GetInterceptorDelegateMethod.MakeGenericMethod(proxyType, topProperty.PropertyType).Invoke((object)null, new object[2] { (object)member, (object)proxyTypeInfo.EntityWrapperDelegate }) as Delegate, field); }
// <summary> // Build a CLR proxy type for the supplied EntityType. // </summary> // <param name="ospaceEntityType"> EntityType in O-Space that represents the CLR type to be proxied. </param> // <returns> EntityProxyTypeInfo object that contains the constructed proxy type, along with any behaviors associated with that type; or null if a proxy type cannot be constructed for the specified EntityType. </returns> private static EntityProxyTypeInfo BuildType( ModuleBuilder moduleBuilder, ClrEntityType ospaceEntityType, MetadataWorkspace workspace) { Debug.Assert( _typeMapLock.IsUpgradeableReadLockHeld, "EntityProxyTypeInfo.BuildType method was called without first acquiring an upgradeable read lock from _typeMapLock."); EntityProxyTypeInfo proxyTypeInfo; var proxyTypeBuilder = new ProxyTypeBuilder(ospaceEntityType); var proxyType = proxyTypeBuilder.CreateType(moduleBuilder); if (proxyType != null) { // Set the runtime assembly of the proxy types if it hasn't already been set. // This is used by the IsProxyType method. var typeAssembly = proxyType.Assembly(); if (!_proxyRuntimeAssemblies.Contains(typeAssembly)) { _proxyRuntimeAssemblies.Add(typeAssembly); AddAssemblyToResolveList(typeAssembly); } proxyTypeInfo = new EntityProxyTypeInfo( proxyType, ospaceEntityType, proxyTypeBuilder.CreateInitalizeCollectionMethod(proxyType), proxyTypeBuilder.BaseGetters, proxyTypeBuilder.BaseSetters, workspace); foreach (var member in proxyTypeBuilder.LazyLoadMembers) { InterceptMember(member, proxyType, proxyTypeInfo); } SetResetFKSetterFlagDelegate(proxyType, proxyTypeInfo); SetCompareByteArraysDelegate(proxyType); } else { proxyTypeInfo = null; } return(proxyTypeInfo); }
internal static EntityProxyTypeInfo GetProxyType( ClrEntityType ospaceEntityType, MetadataWorkspace workspace) { EntityProxyTypeInfo proxyTypeInfo = (EntityProxyTypeInfo)null; if (EntityProxyFactory.TryGetProxyType(ospaceEntityType.ClrType, ospaceEntityType.CSpaceTypeName, out proxyTypeInfo)) { proxyTypeInfo?.ValidateType(ospaceEntityType); return(proxyTypeInfo); } EntityProxyFactory._typeMapLock.EnterUpgradeableReadLock(); try { return(EntityProxyFactory.TryCreateProxyType((EntityType)ospaceEntityType, workspace)); } finally { EntityProxyFactory._typeMapLock.ExitUpgradeableReadLock(); } }
/// <summary> /// Build a CLR proxy type for the supplied EntityType. /// </summary> /// <param name="ospaceEntityType"> EntityType in O-Space that represents the CLR type to be proxied. </param> /// <returns> EntityProxyTypeInfo object that contains the constructed proxy type, along with any behaviors associated with that type; or null if a proxy type cannot be constructed for the specified EntityType. </returns> private static EntityProxyTypeInfo BuildType( ModuleBuilder moduleBuilder, ClrEntityType ospaceEntityType, MetadataWorkspace workspace) { Debug.Assert( _typeMapLock.IsUpgradeableReadLockHeld, "EntityProxyTypeInfo.BuildType method was called without first acquiring an upgradeable read lock from _typeMapLock."); EntityProxyTypeInfo proxyTypeInfo; var proxyTypeBuilder = new ProxyTypeBuilder(ospaceEntityType); var proxyType = proxyTypeBuilder.CreateType(moduleBuilder); if (proxyType != null) { // Set the runtime assembly of the proxy types if it hasn't already been set. // This is used by the IsProxyType method. var typeAssembly = proxyType.Assembly; if (!_proxyRuntimeAssemblies.Contains(typeAssembly)) { _proxyRuntimeAssemblies.Add(typeAssembly); AddAssemblyToResolveList(typeAssembly); } proxyTypeInfo = new EntityProxyTypeInfo( proxyType, ospaceEntityType, proxyTypeBuilder.CreateInitalizeCollectionMethod(proxyType), proxyTypeBuilder.BaseGetters, proxyTypeBuilder.BaseSetters, workspace); foreach (var member in proxyTypeBuilder.LazyLoadMembers) { InterceptMember(member, proxyType, proxyTypeInfo); } SetResetFKSetterFlagDelegate(proxyType, proxyTypeInfo); SetCompareByteArraysDelegate(proxyType); } else { proxyTypeInfo = null; } return proxyTypeInfo; }
internal static bool TryGetProxyType(Type clrType, string entityTypeName, out EntityProxyTypeInfo proxyTypeInfo) { _typeMapLock.EnterReadLock(); try { return _proxyNameMap.TryGetValue(new Tuple<Type, string>(clrType, entityTypeName), out proxyTypeInfo); } finally { _typeMapLock.ExitReadLock(); } }
/// <summary> /// Sets a delegate onto the _resetFKSetterFlag field such that it can be executed to make /// a call into the state manager to reset the InFKSetter flag. /// </summary> private static void SetResetFKSetterFlagDelegate(Type proxyType, EntityProxyTypeInfo proxyTypeInfo) { var resetFKSetterFlagField = proxyType.GetField( ResetFKSetterFlagFieldName, BindingFlags.DeclaredOnly | BindingFlags.Static | BindingFlags.NonPublic); Debug.Assert(resetFKSetterFlagField != null, "Expected resetFKSetterFlagField to be defined on the proxy type."); var resetFKSetterFlagDelegate = GetResetFKSetterFlagDelegate(proxyTypeInfo.EntityWrapperDelegate); AssignInterceptionDelegate(resetFKSetterFlagDelegate, resetFKSetterFlagField); }
/// <summary> /// Construct an interception delegate for the specified proxy member. /// </summary> /// <param name="member"> EdmMember that specifies the member to be intercepted. </param> /// <param name="proxyType"> Type of the proxy. </param> /// <param name="lazyLoadBehavior"> LazyLoadBehavior object that supplies the behavior to load related ends. </param> private static void InterceptMember(EdmMember member, Type proxyType, EntityProxyTypeInfo proxyTypeInfo) { var property = EntityUtil.GetTopProperty(proxyType, member.Name); Debug.Assert( property != null, String.Format( CultureInfo.CurrentCulture, "Expected property {0} to be defined on proxy type {1}", member.Name, proxyType.FullName)); var interceptorField = proxyType.GetField( LazyLoadImplementor.GetInterceptorFieldName(member.Name), BindingFlags.DeclaredOnly | BindingFlags.Static | BindingFlags.NonPublic); Debug.Assert( interceptorField != null, String.Format( CultureInfo.CurrentCulture, "Expected interceptor field for property {0} to be defined on proxy type {1}", member.Name, proxyType.FullName)); var interceptorDelegate = typeof(LazyLoadBehavior).GetMethod("GetInterceptorDelegate", BindingFlags.NonPublic | BindingFlags.Static). MakeGenericMethod(proxyType, property.PropertyType). Invoke(null, new object[] { member, proxyTypeInfo.EntityWrapperDelegate }) as Delegate; AssignInterceptionDelegate(interceptorDelegate, interceptorField); }
internal static bool TryGetProxyType(Type proxyType, out EntityProxyTypeInfo proxyTypeInfo) { _typeMapLock.EnterReadLock(); try { return _proxyTypeMap.TryGetValue(proxyType, out proxyTypeInfo); } finally { _typeMapLock.ExitReadLock(); } }