示例#1
0
        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);
        }
示例#2
0
        // <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();
            }
        }
示例#3
0
        // <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);
        }
示例#4
0
        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);
        }
示例#5
0
        /// <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());
            }
        }
示例#7
0
        // <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);
        }
示例#8
0
 internal static bool TryGetProxyType(Type proxyType, out EntityProxyTypeInfo proxyTypeInfo)
 {
     _typeMapLock.EnterReadLock();
     try
     {
         return(_proxyTypeMap.TryGetValue(proxyType, out proxyTypeInfo));
     }
     finally
     {
         _typeMapLock.ExitReadLock();
     }
 }
示例#9
0
 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();
     }
 }
示例#10
0
        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);
            }
        }
示例#12
0
 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;
     })));
 }
示例#13
0
        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);
        }
示例#14
0
        // <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);
        }
示例#15
0
        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();
     }
 }