/// <summary>
 /// Given the type in the target space and the member name in the source space,
 /// get the corresponding member in the target space
 /// For e.g.  consider a Conceptual Type 'Foo' with a member 'Bar' and a CLR type
 /// 'XFoo' with a member 'YBar'. If one has a reference to Foo one can
 /// invoke GetMember(Foo,"YBar") to retrieve the member metadata for bar
 /// </summary>
 /// <param name="type">The type in the target perspective</param>
 /// <param name="memberName">the name of the member in the source perspective</param>
 /// <param name="ignoreCase">Whether to do case-sensitive member look up or not</param>
 /// <param name="outMember">returns the member in target space, if a match is found</param>
 internal virtual bool TryGetMember(StructuralType type, String memberName, bool ignoreCase, out EdmMember outMember)
 {
     EntityUtil.CheckArgumentNull(type, "type");
     EntityUtil.CheckStringArgument(memberName, "memberName");
     outMember = null;
     return(type.Members.TryGetValue(memberName, ignoreCase, out outMember));
 }
Ejemplo n.º 2
0
        private void AddScalarMember(Type type, PropertyInfo clrProperty, StructuralType ospaceType, EdmProperty cspaceProperty, EdmType propertyType)
        {
            Debug.Assert(type != null, "type != null");
            Debug.Assert(clrProperty != null, "clrProperty != null");
            Debug.Assert(clrProperty.CanRead && clrProperty.CanWrite, "The clr property has to have a setter and a getter.");
            Debug.Assert(ospaceType != null, "ospaceType != null");
            Debug.Assert(cspaceProperty != null, "cspaceProperty != null");
            Debug.Assert(propertyType != null, "propertyType != null");
            Debug.Assert(Helper.IsScalarType(propertyType), "Property has to be primitive or enum.");

            var cspaceType = cspaceProperty.DeclaringType;

            bool isKeyMember = Helper.IsEntityType(cspaceType) && ((EntityType)cspaceType).KeyMemberNames.Contains(clrProperty.Name);

            // the property is nullable only if it is not a key and can actually be set to null (i.e. is not a value type or is a nullable value type)
            bool nullableFacetValue = !isKeyMember && (!clrProperty.PropertyType.IsValueType || Nullable.GetUnderlyingType(clrProperty.PropertyType) != null);

            EdmProperty ospaceProperty =
                new EdmProperty(
                    cspaceProperty.Name,
                    TypeUsage.Create(propertyType, new FacetValues {
                Nullable = nullableFacetValue
            }),
                    clrProperty,
                    type.TypeHandle);

            if (isKeyMember)
            {
                ((EntityType)ospaceType).AddKeyMember(ospaceProperty);
            }
            else
            {
                ospaceType.AddMember(ospaceProperty);
            }
        }
Ejemplo n.º 3
0
        private bool TryFindAndCreateEnumProperties(Type type, StructuralType cspaceType, StructuralType ospaceType, PropertyInfo[] clrProperties, List <Action> referenceResolutionListForCurrentType)
        {
            var typeClosureToTrack = new List <KeyValuePair <EdmProperty, PropertyInfo> >();

            foreach (EdmProperty cspaceProperty in cspaceType.GetDeclaredOnlyMembers <EdmProperty>().Where(p => Helper.IsEnumType(p.TypeUsage.EdmType)))
            {
                PropertyInfo clrProperty = clrProperties.FirstOrDefault(p => MemberMatchesByConvention(p, cspaceProperty));
                if (clrProperty != null)
                {
                    typeClosureToTrack.Add(new KeyValuePair <EdmProperty, PropertyInfo>(cspaceProperty, clrProperty));
                }
                else
                {
                    string message = Strings.Validator_OSpace_Convention_MissingRequiredProperty(cspaceProperty.Name, type.FullName);
                    SessionData.LoadMessageLogger.LogLoadMessage(message, cspaceType);
                    return(false);
                }
            }

            foreach (var typeToTrack in typeClosureToTrack)
            {
                TrackClosure(typeToTrack.Value.PropertyType);
                // prevent the lifting of these closure variables
                var ot   = ospaceType;
                var cp   = typeToTrack.Key;
                var clrp = typeToTrack.Value;
                referenceResolutionListForCurrentType.Add(() => CreateAndAddEnumProperty(type, ot, cp, clrp));
            }

            return(true);
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Creates an Enum property based on <paramref name="clrProperty"/>and adds it to the parent structural type.
        /// </summary>
        /// <param name="type">CLR type owning <paramref name="clrProperty"/>.</param>
        /// <param name="ospaceType">OSpace type the created property will be added to.</param>
        /// <param name="cspaceProperty">Corresponding property from CSpace.</param>
        /// <param name="clrProperty">CLR property used to build an Enum property.</param>
        private void CreateAndAddEnumProperty(Type type, StructuralType ospaceType, EdmProperty cspaceProperty, PropertyInfo clrProperty)
        {
            EdmType propertyType;

            if (SessionData.CspaceToOspace.TryGetValue(cspaceProperty.TypeUsage.EdmType, out propertyType))
            {
                if (clrProperty.CanRead && clrProperty.CanWrite)
                {
                    AddScalarMember(type, clrProperty, ospaceType, cspaceProperty, propertyType);
                }
                else
                {
                    string message =
                        SessionData.LoadMessageLogger.CreateErrorMessageWithTypeSpecificLoadLogs(
                            Strings.Validator_OSpace_Convention_ScalarPropertyMissginGetterOrSetter(clrProperty.Name, type.FullName, type.Assembly.FullName),
                            cspaceProperty.TypeUsage.EdmType);

                    SessionData.EdmItemErrors.Add(new EdmItemError(message, ospaceType));
                }
            }
            else
            {
                string message =
                    SessionData.LoadMessageLogger.CreateErrorMessageWithTypeSpecificLoadLogs(
                        Strings.Validator_OSpace_Convention_MissingOSpaceType(cspaceProperty.TypeUsage.EdmType.FullName),
                        cspaceProperty.TypeUsage.EdmType);

                SessionData.EdmItemErrors.Add(new EdmItemError(message, ospaceType));
            }
        }
Ejemplo n.º 5
0
        private bool TryCreateMembers(Type type, StructuralType cspaceType, StructuralType ospaceType, List <Action> referenceResolutionListForCurrentType)
        {
            BindingFlags flags = cspaceType.BaseType == null ? RootEntityPropertyReflectionBindingFlags : PropertyReflectionBindingFlags;

            PropertyInfo[] clrProperties = type.GetProperties(flags);

            // required properties scalar properties first
            if (!TryFindAndCreatePrimitiveProperties(type, cspaceType, ospaceType, clrProperties))
            {
                return(false);
            }

            if (!TryFindAndCreateEnumProperties(type, cspaceType, ospaceType, clrProperties, referenceResolutionListForCurrentType))
            {
                return(false);
            }

            if (!TryFindComplexProperties(type, cspaceType, ospaceType, clrProperties, referenceResolutionListForCurrentType))
            {
                return(false);
            }

            if (!TryFindNavigationProperties(type, cspaceType, ospaceType, clrProperties, referenceResolutionListForCurrentType))
            {
                return(false);
            }

            return(true);
        }
Ejemplo n.º 6
0
        /// <summary>
        /// Creates a structural OSpace type based on CLR type and CSpace type.
        /// </summary>
        /// <param name="type">CLR type.</param>
        /// <param name="cspaceType">CSpace Type</param>
        /// <param name="newOSpaceType">OSpace type created based on CLR <paramref name="type"/> and <paramref name="cspaceType"/></param>
        /// <returns><c>true</c> if the type was created successfully. Otherwise <c>false</c>.</returns>
        private bool TryCreateStructuralType(Type type, StructuralType cspaceType, out EdmType newOSpaceType)
        {
            Debug.Assert(type != null, "type != null");
            Debug.Assert(cspaceType != null, "cspaceType != null");

            List <Action> referenceResolutionListForCurrentType = new List <Action>();

            newOSpaceType = null;
            Debug.Assert(TypesMatchByConvention(type, cspaceType), "The types passed as parameters don't match by convention.");

            StructuralType ospaceType;

            if (Helper.IsEntityType(cspaceType))
            {
                ospaceType = new ClrEntityType(type, cspaceType.NamespaceName, cspaceType.Name);
            }
            else
            {
                Debug.Assert(Helper.IsComplexType(cspaceType), "Invalid type attribute encountered");
                ospaceType = new ClrComplexType(type, cspaceType.NamespaceName, cspaceType.Name);
            }

            if (cspaceType.BaseType != null)
            {
                if (TypesMatchByConvention(type.BaseType, cspaceType.BaseType))
                {
                    TrackClosure(type.BaseType);
                    referenceResolutionListForCurrentType.Add(
                        () => ospaceType.BaseType = ResolveBaseType((StructuralType)cspaceType.BaseType, type));
                }
                else
                {
                    string message = Strings.Validator_OSpace_Convention_BaseTypeIncompatible(type.BaseType.FullName, type.FullName, cspaceType.BaseType.FullName);
                    SessionData.LoadMessageLogger.LogLoadMessage(message, cspaceType);
                    return(false);
                }
            }

            // Load the properties for this type
            if (!TryCreateMembers(type, (StructuralType)cspaceType, ospaceType, referenceResolutionListForCurrentType))
            {
                return(false);
            }

            // Add this to the known type map so we won't try to load it again
            SessionData.TypesInLoading.Add(type.FullName, ospaceType);

            // we only add the referenceResolution to the list unless we structrually matched this type
            foreach (var referenceResolution in referenceResolutionListForCurrentType)
            {
                this._referenceResolutions.Add(referenceResolution);
            }

            newOSpaceType = ospaceType;
            return(true);
        }
Ejemplo n.º 7
0
        private void CreateAndAddNavigationProperty(StructuralType cspaceType, StructuralType ospaceType, NavigationProperty cspaceProperty, PropertyInfo clrProperty)
        {
            EdmType ospaceRelationship;

            if (SessionData.CspaceToOspace.TryGetValue(cspaceProperty.RelationshipType, out ospaceRelationship))
            {
                Debug.Assert(ospaceRelationship is StructuralType, "Structural type expected.");

                bool    foundTarget = false;
                EdmType targetType  = null;
                if (Helper.IsCollectionType(cspaceProperty.TypeUsage.EdmType))
                {
                    EdmType findType;
                    foundTarget = SessionData.CspaceToOspace.TryGetValue((StructuralType)((CollectionType)cspaceProperty.TypeUsage.EdmType).TypeUsage.EdmType, out findType);
                    if (foundTarget)
                    {
                        Debug.Assert(findType is StructuralType, "Structural type expected.");

                        targetType = findType.GetCollectionType();
                    }
                }
                else
                {
                    EdmType findType;
                    foundTarget = SessionData.CspaceToOspace.TryGetValue((StructuralType)cspaceProperty.TypeUsage.EdmType, out findType);
                    if (foundTarget)
                    {
                        Debug.Assert(findType is StructuralType, "Structural type expected.");

                        targetType = findType;
                    }
                }


                Debug.Assert(foundTarget, "Since the relationship will only be created if it can find the types for both ends, we will never fail to find one of the ends");

                NavigationProperty navigationProperty = new NavigationProperty(cspaceProperty.Name, TypeUsage.Create(targetType), clrProperty);
                navigationProperty.RelationshipType = (RelationshipType)ospaceRelationship;

                // we can use First because o-space relationships are created directly from
                // c-space relationship
                navigationProperty.ToEndMember   = (RelationshipEndMember)((RelationshipType)ospaceRelationship).Members.First(e => e.Name == cspaceProperty.ToEndMember.Name);
                navigationProperty.FromEndMember = (RelationshipEndMember)((RelationshipType)ospaceRelationship).Members.First(e => e.Name == cspaceProperty.FromEndMember.Name);
                ospaceType.AddMember(navigationProperty);
            }
            else
            {
                EntityTypeBase missingType = cspaceProperty.RelationshipType.RelationshipEndMembers.Select(e => ((RefType)e.TypeUsage.EdmType).ElementType).First(e => e != cspaceType);
                string         message     =
                    SessionData.LoadMessageLogger.CreateErrorMessageWithTypeSpecificLoadLogs(
                        Strings.Validator_OSpace_Convention_RelationshipNotLoaded(cspaceProperty.RelationshipType.FullName, missingType.FullName),
                        missingType);
                SessionData.EdmItemErrors.Add(new EdmItemError(message, ospaceType));
            }
        }
Ejemplo n.º 8
0
        /// <summary>
        /// Get the number of members the base type has.  If the base type is not a structural type or has no
        /// members, it returns 0
        /// </summary>
        /// <returns>The number of members in the base type</returns>
        private int GetBaseTypeMemberCount()
        {
            // The count of members is what in this collection plus base type's member collection
            StructuralType baseType = _declaringType.BaseType as StructuralType;

            if (baseType != null)
            {
                return(baseType.Members.Count);
            }

            return(0);
        }
Ejemplo n.º 9
0
        private EdmType ResolveBaseType(StructuralType baseCSpaceType, Type type)
        {
            EdmType ospaceType;
            bool    foundValue = SessionData.CspaceToOspace.TryGetValue(baseCSpaceType, out ospaceType);

            if (!foundValue)
            {
                string message =
                    SessionData.LoadMessageLogger.CreateErrorMessageWithTypeSpecificLoadLogs(
                        Strings.Validator_OSpace_Convention_BaseTypeNotLoaded(type, baseCSpaceType),
                        baseCSpaceType);
                SessionData.EdmItemErrors.Add(new EdmItemError(message, ospaceType));
            }

            Debug.Assert(!foundValue || ospaceType is StructuralType, "Structural type expected (if found).");

            return(ospaceType);
        }
Ejemplo n.º 10
0
        private bool TryFindNavigationProperties(Type type, StructuralType cspaceType, StructuralType ospaceType, PropertyInfo[] clrProperties, List <Action> referenceResolutionListForCurrentType)
        {
            List <KeyValuePair <NavigationProperty, PropertyInfo> > typeClosureToTrack =
                new List <KeyValuePair <NavigationProperty, PropertyInfo> >();

            foreach (NavigationProperty cspaceProperty in cspaceType.GetDeclaredOnlyMembers <NavigationProperty>())
            {
                PropertyInfo clrProperty = clrProperties.FirstOrDefault(p => NonPrimitiveMemberMatchesByConvention(p, cspaceProperty));
                if (clrProperty != null)
                {
                    bool needsSetter = cspaceProperty.ToEndMember.RelationshipMultiplicity != RelationshipMultiplicity.Many;
                    if (clrProperty.CanRead && (!needsSetter || clrProperty.CanWrite))
                    {
                        typeClosureToTrack.Add(
                            new KeyValuePair <NavigationProperty, PropertyInfo>(
                                cspaceProperty, clrProperty));
                    }
                }
                else
                {
                    string message = Strings.Validator_OSpace_Convention_MissingRequiredProperty(
                        cspaceProperty.Name, type.FullName);
                    SessionData.LoadMessageLogger.LogLoadMessage(message, cspaceType);
                    return(false);
                }
            }

            foreach (var typeToTrack in typeClosureToTrack)
            {
                TrackClosure(typeToTrack.Value.PropertyType);

                // keep from lifting these closure variables
                var ct   = cspaceType;
                var ot   = ospaceType;
                var cp   = typeToTrack.Key;
                var clrp = typeToTrack.Value;

                referenceResolutionListForCurrentType.Add(() => CreateAndAddNavigationProperty(ct, ot, cp, clrp));
            }

            return(true);
        }
Ejemplo n.º 11
0
        /// <summary>
        /// Find the index of an item
        /// </summary>
        /// <param name="item">The item whose index is to be looked for</param>
        /// <returns>The index of the found item, -1 if not found</returns>
        public override int IndexOf(EdmMember item)
        {
            // Try to get it from this collection, if found, then the relative index needs to be added with the number
            // of members in the base type to get the absolute index
            int relativeIndex = base.IndexOf(item);

            if (relativeIndex != -1)
            {
                return(relativeIndex + GetBaseTypeMemberCount());
            }

            // Try to find it in the base type
            StructuralType baseType = _declaringType.BaseType as StructuralType;

            if (baseType != null)
            {
                return(baseType.Members.IndexOf(item));
            }

            return(-1);
        }
Ejemplo n.º 12
0
        /// <summary>
        /// Given the type in the target space and the member name in the source space,
        /// get the corresponding member in the target space
        /// For e.g.  consider a Conceptual Type Foo with a member bar and a CLR type
        /// XFoo with a member YBar. If one has a reference to Foo one can
        /// invoke GetMember(Foo,"YBar") to retrieve the member metadata for bar
        /// </summary>
        /// <param name="type">The type in the target perspective</param>
        /// <param name="memberName">the name of the member in the source perspective</param>
        /// <param name="ignoreCase">true for case-insensitive lookup</param>
        /// <param name="outMember">returns the edmMember if a match is found</param>
        /// <returns>true if a match is found, otherwise false</returns>
        internal override bool TryGetMember(StructuralType type, String memberName, bool ignoreCase, out EdmMember outMember)
        {
            outMember = null;
            Map map = null;

            if (this.MetadataWorkspace.TryGetMap(type, DataSpace.OCSpace, out map))
            {
                ObjectTypeMapping objectTypeMap = map as ObjectTypeMapping;

                if (objectTypeMap != null)
                {
                    ObjectMemberMapping objPropertyMapping = objectTypeMap.GetMemberMapForClrMember(memberName, ignoreCase);
                    if (null != objPropertyMapping)
                    {
                        outMember = objPropertyMapping.EdmMember;
                        return(true);
                    }
                }
            }
            return(false);
        }
        /// <summary>
        /// Resolves enum type property.
        /// </summary>
        /// <param name="declaringType">The type to add the declared property to.</param>
        /// <param name="clrProperty">Property to resolve.</param>
        private void ResolveEnumTypeProperty(StructuralType declaringType, PropertyInfo clrProperty)
        {
            Debug.Assert(declaringType != null, "type != null");
            Debug.Assert(clrProperty != null, "clrProperty != null");
            Debug.Assert(
                (Nullable.GetUnderlyingType(clrProperty.PropertyType) ?? clrProperty.PropertyType).IsEnum,
                "This method should be called for enums only");

            EdmType propertyType;

            if (!TryGetLoadedType(clrProperty.PropertyType, out propertyType) || !Helper.IsEnumType(propertyType))
            {
                SessionData.EdmItemErrors.Add(
                    new EdmItemError(
                        System.Data.Entity.Strings.Validator_OSpace_ScalarPropertyNotPrimitive(
                            clrProperty.Name,
                            clrProperty.DeclaringType.FullName,
                            clrProperty.PropertyType.FullName), null));
            }
            else
            {
                var edmScalarPropertyAttribute = (EdmScalarPropertyAttribute)clrProperty.GetCustomAttributes(typeof(EdmScalarPropertyAttribute), false).Single();

                EdmProperty enumProperty = new EdmProperty(
                    clrProperty.Name,
                    TypeUsage.Create(propertyType, new FacetValues()
                {
                    Nullable = edmScalarPropertyAttribute.IsNullable
                }),
                    clrProperty,
                    declaringType.ClrType.TypeHandle);

                declaringType.AddMember(enumProperty);

                if (declaringType.BuiltInTypeKind == BuiltInTypeKind.EntityType && edmScalarPropertyAttribute.EntityKeyProperty)
                {
                    ((EntityType)declaringType).AddKeyMember(enumProperty);
                }
            }
        }
Ejemplo n.º 14
0
        private void CreateAndAddComplexType(Type type, StructuralType ospaceType, EdmProperty cspaceProperty, PropertyInfo clrProperty)
        {
            EdmType propertyType;

            if (SessionData.CspaceToOspace.TryGetValue((StructuralType)cspaceProperty.TypeUsage.EdmType, out propertyType))
            {
                Debug.Assert(propertyType is StructuralType, "Structural type expected.");

                EdmProperty property = new EdmProperty(cspaceProperty.Name, TypeUsage.Create(propertyType, new FacetValues {
                    Nullable = false
                }), clrProperty, type.TypeHandle);
                ospaceType.AddMember(property);
            }
            else
            {
                string message =
                    SessionData.LoadMessageLogger.CreateErrorMessageWithTypeSpecificLoadLogs(
                        Strings.Validator_OSpace_Convention_MissingOSpaceType(cspaceProperty.TypeUsage.EdmType.FullName),
                        cspaceProperty.TypeUsage.EdmType);
                SessionData.EdmItemErrors.Add(new EdmItemError(message, ospaceType));
            }
        }
        /// <summary>
        /// Validate an StructuralType object
        /// </summary>
        /// <param name="item">The StructuralType object to validate</param>
        /// <param name="errors">An error collection for adding validation errors</param>
        /// <param name="validatedItems">A dictionary keeping track of items that have been validated</param>
        private void ValidateStructuralType(StructuralType item, List <EdmItemError> errors, HashSet <MetadataItem> validatedItems)
        {
            ValidateEdmType(item, errors, validatedItems);

            // Just validate each member, the collection already guaranteed that there aren't any nulls in the collection
            Dictionary <string, EdmMember> allMembers = new Dictionary <string, EdmMember>();

            foreach (EdmMember member in item.Members)
            {
                // Check if the base type already has a member of the same name
                EdmMember baseMember = null;
                if (allMembers.TryGetValue(member.Name, out baseMember))
                {
                    AddError(errors, new EdmItemError(System.Data.Entity.Strings.Validator_BaseTypeHasMemberOfSameName, item));
                }
                else
                {
                    allMembers.Add(member.Name, member);
                }

                InternalValidate(member, errors, validatedItems);
            }
        }
Ejemplo n.º 16
0
 private bool TryFindAndCreatePrimitiveProperties(Type type, StructuralType cspaceType, StructuralType ospaceType, PropertyInfo[] clrProperties)
 {
     foreach (EdmProperty cspaceProperty in cspaceType.GetDeclaredOnlyMembers <EdmProperty>().Where(p => Helper.IsPrimitiveType(p.TypeUsage.EdmType)))
     {
         PropertyInfo clrProperty = clrProperties.FirstOrDefault(p => MemberMatchesByConvention(p, cspaceProperty));
         if (clrProperty != null)
         {
             PrimitiveType propertyType;
             if (TryGetPrimitiveType(clrProperty.PropertyType, out propertyType))
             {
                 if (clrProperty.CanRead && clrProperty.CanWrite)
                 {
                     AddScalarMember(type, clrProperty, ospaceType, cspaceProperty, propertyType);
                 }
                 else
                 {
                     string message = Strings.Validator_OSpace_Convention_ScalarPropertyMissginGetterOrSetter(clrProperty.Name, type.FullName, type.Assembly.FullName);
                     SessionData.LoadMessageLogger.LogLoadMessage(message, cspaceType);
                     return(false);
                 }
             }
             else
             {
                 string message = Strings.Validator_OSpace_Convention_NonPrimitiveTypeProperty(clrProperty.Name, type.FullName, clrProperty.PropertyType.FullName);
                 SessionData.LoadMessageLogger.LogLoadMessage(message, cspaceType);
                 return(false);
             }
         }
         else
         {
             string message = Strings.Validator_OSpace_Convention_MissingRequiredProperty(cspaceProperty.Name, type.FullName);
             SessionData.LoadMessageLogger.LogLoadMessage(message, cspaceType);
             return(false);
         }
     }
     return(true);
 }
        private void ResolveComplexTypeProperty(StructuralType type, PropertyInfo clrProperty)
        {
            // Load the property type and create a new property object
            EdmType propertyType;

            // If the type could not be loaded it's definitely not a complex type, so that's an error
            // If it could be loaded but is not a complex type that's an error as well
            if (!TryGetLoadedType(clrProperty.PropertyType, out propertyType) || propertyType.BuiltInTypeKind != BuiltInTypeKind.ComplexType)
            {
                // This property does not need to be validated further, just add to the errors collection and continue with the next property
                // This 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_ComplexPropertyNotComplex(clrProperty.Name, clrProperty.DeclaringType.FullName, clrProperty.PropertyType.FullName), null));
            }
            else
            {
                EdmProperty newProperty = new EdmProperty(clrProperty.Name,
                                                          TypeUsage.Create(propertyType, new FacetValues {
                    Nullable = false
                }),
                                                          clrProperty, type.ClrType.TypeHandle);

                type.AddMember(newProperty);
            }
        }
Ejemplo n.º 18
0
 /// <summary>
 /// The method returns the underlying CLR type for the specified OSpace type argument.
 /// If the DataSpace of the parameter is not OSpace, the method returns false and sets
 /// the out parameter to null.
 /// </summary>
 /// <param name="objectSpaceType">The OSpace type to look up</param>
 /// <param name="clrType">The CLR type of the OSpace argument</param>
 /// <returns>true on success, false on failure</returns>
 public bool TryGetClrType(StructuralType objectSpaceType, out Type clrType)
 {
     return(ObjectItemCollection.TryGetClrType((EdmType)objectSpaceType, out clrType));
 }
Ejemplo n.º 19
0
 /// <summary>
 /// The method returns the underlying CLR type for the specified OSpace type argument.
 /// If the DataSpace of the parameter is not OSpace, an ArgumentException is thrown.
 /// </summary>
 /// <param name="objectSpaceType">The OSpace type to look up</param>
 /// <returns>The CLR type of the OSpace argument</returns>
 public Type GetClrType(StructuralType objectSpaceType)
 {
     return(ObjectItemCollection.GetClrType((EdmType)objectSpaceType));
 }
        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);
            }
        }
        /// <summary>
        /// Load all the property metadata of the given type
        /// </summary>
        /// <param name="type">The CLR entity type</param>
        /// <param name="structuralType">The type where properties are loaded</param>
        /// <param name="context"></param>
        private void LoadPropertiesFromType(StructuralType structuralType)
        {
            // Look at both public, internal, and private instanced properties declared at this type, inherited members
            // are not looked at.  Internal and private properties are also looked at because they are also schematized fields
            PropertyInfo[] properties = structuralType.ClrType.GetProperties(PropertyReflectionBindingFlags);

            foreach (PropertyInfo property in properties)
            {
                EdmMember newMember           = null;
                bool      isEntityKeyProperty = false; //used for EdmScalarProperties only

                // 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.
                if (property.IsDefined(typeof(EdmRelationshipNavigationPropertyAttribute), false))
                {
                    // keep the loop var from being lifted
                    PropertyInfo pi = property;
                    _unresolvedNavigationProperties.Add(() =>
                                                        ResolveNavigationProperty(structuralType, pi));
                }
                else if (property.IsDefined(typeof(EdmScalarPropertyAttribute), false))
                {
                    if ((Nullable.GetUnderlyingType(property.PropertyType) ?? property.PropertyType).IsEnum)
                    {
                        TrackClosure(property.PropertyType);
                        PropertyInfo local = property;
                        AddTypeResolver(() => ResolveEnumTypeProperty(structuralType, local));
                    }
                    else
                    {
                        newMember = LoadScalarProperty(structuralType.ClrType, property, out isEntityKeyProperty);
                    }
                }
                else if (property.IsDefined(typeof(EdmComplexPropertyAttribute), false))
                {
                    TrackClosure(property.PropertyType);
                    // keep loop var from being lifted
                    PropertyInfo local = property;
                    AddTypeResolver(() => ResolveComplexTypeProperty(structuralType, local));
                }

                if (newMember == null)
                {
                    // Property does not have one of the following attributes:
                    //     EdmScalarPropertyAttribute, EdmComplexPropertyAttribute, EdmRelationshipNavigationPropertyAttribute
                    // This means its an unmapped property and can be ignored.
                    // Or there were error encountered while loading the properties
                    continue;
                }

                // Add the property object to the type
                structuralType.AddMember(newMember);

                // Add to the entity's collection of key members
                // Do this here instead of in the if condition above for scalar properties because
                // we want to make sure the AddMember call above did not fail before updating the key members
                if (Helper.IsEntityType(structuralType) && isEntityKeyProperty)
                {
                    ((EntityType)structuralType).AddKeyMember(newMember);
                }
            }
        }
Ejemplo n.º 22
0
 /// <summary>
 /// Change the declaring type without doing fixup in the member collection
 /// </summary>
 internal void ChangeDeclaringTypeWithoutCollectionFixup(StructuralType newDeclaringType)
 {
     _declaringType = newDeclaringType;
 }
Ejemplo n.º 23
0
 /// <summary>
 /// The constructor for constructing the collection with the given items
 /// </summary>
 /// <param name="declaringType">The type that has this member collection</param>
 /// <param name="items">The items to populate the collection</param>
 /// <exception cref="System.ArgumentNullException">Thrown if the declaring type is null</exception>
 public MemberCollection(StructuralType declaringType, IEnumerable <EdmMember> items)
     : base(items)
 {
     Debug.Assert(declaringType != null, "This member collection must belong to a declaring type");
     _declaringType = declaringType;
 }
Ejemplo n.º 24
0
        // This way this collection works is that it has storage for members on the current type and access to
        // members in the base types. As of that requirement, MemberCollection has a reference back to the declaring
        // type that owns this collection. Whenever MemberCollection is asked to do a look by name, it looks at the
        // current collection, if it doesn't find it, then it ask for it from the declaring type's base type's
        // MemberCollection. Because of this order, members in derived types hide members in the base type if they
        // have the same name. For look up by index, base type members have lower index then current type's members.
        // Add/Update/Remove operations on this collection is only allowed for members owned by this MemberCollection
        // and not allowed for members owned by MemberCollections in the base types. For example, if the caller tries
        // to remove a member by ordinal which is within the base type's member ordinal range, it throws an exception.
        // Hence, base type members are in a sense "readonly" to this MemberCollection. When enumerating all the
        // members, the enumeration starts from members in the root type in the inheritance chain. With this special
        // enumeration requirement, we have a specialized enumerator class for this MemberCollection. See the
        // Enumerator class for details on how it works.

        #region Constructors
        /// <summary>
        /// Default constructor for constructing an empty collection
        /// </summary>
        /// <param name="declaringType">The type that has this member collection</param>
        /// <exception cref="System.ArgumentNullException">Thrown if the declaring type is null</exception>
        public MemberCollection(StructuralType declaringType)
            : this(declaringType, null)
        {
        }