/// <summary>
        /// internal static method to get all the AssociationTypes from an assembly
        /// </summary>
        /// <param name="assembly">The assembly from which to load relationship types</param>
        /// <returns>An enumeration of OSpace AssociationTypes that are present in this assembly</returns>
        internal static IEnumerable <AssociationType> GetAllRelationshipTypesExpensiveWay(Assembly assembly)
        {
            Dictionary <string, EdmType> typesInLoading = LoadTypesExpensiveWay(assembly);

            if (typesInLoading != null)
            {
                // Iterate through the EdmTypes looking for AssociationTypes
                foreach (EdmType edmType in typesInLoading.Values)
                {
                    if (Helper.IsAssociationType(edmType))
                    {
                        yield return((AssociationType)edmType);
                    }
                }
            }
            yield break;
        }
Beispiel #2
0
        internal ObjectItemLoadingSessionData(KnownAssembliesSet knownAssemblies, LockedAssemblyCache lockedAssemblyCache, EdmItemCollection edmItemCollection, Action <String> logLoadMessage, object loaderCookie)
        {
            Debug.Assert(loaderCookie == null || loaderCookie is Func <Assembly, ObjectItemLoadingSessionData, ObjectItemAssemblyLoader>, "This is a bad loader cookie");

            _typesInLoading      = new Dictionary <string, EdmType>(StringComparer.Ordinal);
            _errors              = new List <EdmItemError>();
            _knownAssemblies     = knownAssemblies;
            _lockedAssemblyCache = lockedAssemblyCache;
            _loadersThatNeedLevel1PostSessionProcessing = new HashSet <ObjectItemAssemblyLoader>();
            _loadersThatNeedLevel2PostSessionProcessing = new HashSet <ObjectItemAssemblyLoader>();
            _edmItemCollection    = edmItemCollection;
            _loadMessageLogger    = new LoadMessageLogger(logLoadMessage);
            _cspaceToOspace       = new Dictionary <EdmType, EdmType>();
            _loaderFactory        = (Func <Assembly, ObjectItemLoadingSessionData, ObjectItemAssemblyLoader>)loaderCookie;
            _originalLoaderCookie = loaderCookie;
            if (_loaderFactory == ObjectItemConventionAssemblyLoader.Create && _edmItemCollection != null)
            {
                foreach (KnownAssemblyEntry entry in _knownAssemblies.GetEntries(_loaderFactory, edmItemCollection))
                {
                    foreach (EdmType type in entry.CacheEntry.TypesInAssembly.OfType <EdmType>())
                    {
                        if (Helper.IsEntityType(type))
                        {
                            ClrEntityType entityType = (ClrEntityType)type;
                            _cspaceToOspace.Add(_edmItemCollection.GetItem <StructuralType>(entityType.CSpaceTypeName), entityType);
                        }
                        else if (Helper.IsComplexType(type))
                        {
                            ClrComplexType complexType = (ClrComplexType)type;
                            _cspaceToOspace.Add(_edmItemCollection.GetItem <StructuralType>(complexType.CSpaceTypeName), complexType);
                        }
                        else if (Helper.IsEnumType(type))
                        {
                            ClrEnumType enumType = (ClrEnumType)type;
                            _cspaceToOspace.Add(_edmItemCollection.GetItem <EnumType>(enumType.CSpaceTypeName), enumType);
                        }
                        else
                        {
                            Debug.Assert(Helper.IsAssociationType(type));
                            _cspaceToOspace.Add(_edmItemCollection.GetItem <StructuralType>(type.FullName), type);
                        }
                    }
                }
            }
        }
        internal void ResolveNavigationProperty(StructuralType declaringType, PropertyInfo propertyInfo)
        {
            Debug.Assert(propertyInfo.IsDefined(typeof(EdmRelationshipNavigationPropertyAttribute), false), "The property must have navigation property defined");

            // EdmScalarPropertyAttribute, EdmComplexPropertyAttribute and EdmRelationshipNavigationPropertyAttribute
            // are all EdmPropertyAttributes that we need to process. If the current property is not an EdmPropertyAttribute
            // we will just ignore it and skip to the next property.
            object[] relationshipPropertyAttributes = propertyInfo.GetCustomAttributes(typeof(EdmRelationshipNavigationPropertyAttribute), false);

            Debug.Assert(relationshipPropertyAttributes.Length == 1, "There should be exactly one property for every navigation property");

            // The only valid return types from navigation properties are:
            //     (1) EntityType
            //     (2) CollectionType containing valid EntityType

            // If TryGetLoadedType returned false, it could mean that we couldn't validate any part of the type, or it could mean that it's a generic
            // where the main generic type was validated, but the generic type parameter was not. We can't tell the difference, so just fail
            // with the same error message in both cases. The user will have to figure out which part of the type is wrong.
            // We can't just rely on checking for a generic because it can lead to a scenario where we report that the type parameter is invalid
            // when really it's the main generic type. That is more confusing than reporting the full name and letting the user determine the problem.
            EdmType propertyType;

            if (!TryGetLoadedType(propertyInfo.PropertyType, out propertyType) || !(propertyType.BuiltInTypeKind == BuiltInTypeKind.EntityType || propertyType.BuiltInTypeKind == BuiltInTypeKind.CollectionType))
            {
                // Once an error is detected the property does not need to be validated further, just add to the errors
                // collection and continue with the next property. The failure will cause an exception to be thrown later during validation of all of the types.
                SessionData.EdmItemErrors.Add(new EdmItemError(System.Data.Entity.Strings.Validator_OSpace_InvalidNavPropReturnType(propertyInfo.Name, propertyInfo.DeclaringType.FullName, propertyInfo.PropertyType.FullName), null));
                return;
            }
            // else we have a valid EntityType or CollectionType that contains EntityType. ResolveNonSchemaType enforces that a collection type
            // must contain an EntityType, and if it doesn't, propertyType will be null here. If propertyType is EntityType or CollectionType we know it is valid

            // Expecting EdmRelationshipNavigationPropertyAttribute to have AllowMultiple=False, so only look at first element in the attribute array

            EdmRelationshipNavigationPropertyAttribute attribute = (EdmRelationshipNavigationPropertyAttribute)relationshipPropertyAttributes[0];

            EdmMember member = null;
            EdmType   type;

            if (SessionData.TypesInLoading.TryGetValue(attribute.RelationshipNamespaceName + "." + attribute.RelationshipName, out type) &&
                Helper.IsAssociationType(type))
            {
                AssociationType relationshipType = (AssociationType)type;
                if (relationshipType != null)
                {
                    // The return value of this property has been verified, so create the property now
                    NavigationProperty navigationProperty = new NavigationProperty(propertyInfo.Name, TypeUsage.Create(propertyType), propertyInfo);
                    navigationProperty.RelationshipType = relationshipType;
                    member = navigationProperty;

                    if (relationshipType.Members[0].Name == attribute.TargetRoleName)
                    {
                        navigationProperty.ToEndMember   = (RelationshipEndMember)relationshipType.Members[0];
                        navigationProperty.FromEndMember = (RelationshipEndMember)relationshipType.Members[1];
                    }
                    else if (relationshipType.Members[1].Name == attribute.TargetRoleName)
                    {
                        navigationProperty.ToEndMember   = (RelationshipEndMember)relationshipType.Members[1];
                        navigationProperty.FromEndMember = (RelationshipEndMember)relationshipType.Members[0];
                    }
                    else
                    {
                        SessionData.EdmItemErrors.Add(new EdmItemError(System.Data.Entity.Strings.TargetRoleNameInNavigationPropertyNotValid(
                                                                           propertyInfo.Name, propertyInfo.DeclaringType.FullName, attribute.TargetRoleName, attribute.RelationshipName), navigationProperty));
                        member = null;
                    }

                    if (member != null &&
                        ((RefType)navigationProperty.FromEndMember.TypeUsage.EdmType).ElementType.ClrType != declaringType.ClrType)
                    {
                        SessionData.EdmItemErrors.Add(new EdmItemError(System.Data.Entity.Strings.NavigationPropertyRelationshipEndTypeMismatch(
                                                                           declaringType.FullName,
                                                                           navigationProperty.Name,
                                                                           relationshipType.FullName,
                                                                           navigationProperty.FromEndMember.Name,
                                                                           ((RefType)navigationProperty.FromEndMember.TypeUsage.EdmType).ElementType.ClrType), navigationProperty));
                        member = null;
                    }
                }
            }
            else
            {
                SessionData.EdmItemErrors.Add(new EdmItemError(System.Data.Entity.Strings.RelationshipNameInNavigationPropertyNotValid(
                                                                   propertyInfo.Name, propertyInfo.DeclaringType.FullName, attribute.RelationshipName), declaringType));
            }

            if (member != null)
            {
                declaringType.AddMember(member);
            }
        }