예제 #1
0
        /// <summary>
        /// Marks the EpmInfo as initialized and verifies that it's valid.
        /// </summary>
        private void MarkEpmInfoInitialized()
        {
            this.epmInfoInitialized = true;

            EpmResourceTypeAnnotation epm = this.Epm();

            if (epm != null)
            {
                epm.EpmSourceTree.Validate(this);
                epm.EpmTargetTree.Validate();
            }
        }
예제 #2
0
        /// <summary>
        /// Check whether the EPM on the specified resource type is supported in the specified version.
        /// </summary>
        /// <param name="version">The version to check.</param>
        /// <param name="resourceType">The entity resoure type to check.</param>
        internal static void CheckEntityPropertyMapping(ODataVersion version, ResourceType resourceType)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(resourceType != null, "resourceType != null");

            EpmResourceTypeAnnotation epmAnnotation = resourceType.Epm();

            if (epmAnnotation != null)
            {
                Debug.Assert(epmAnnotation.EpmTargetTree != null, "If the EPM annotation is present the EPM tree must already be initialized.");
                if (version < epmAnnotation.EpmTargetTree.MinimumODataProtocolVersion)
                {
                    throw new ODataException(
                              Strings.ODataVersionChecker_EpmVersionNotSupported(
                                  resourceType.FullName,
                                  epmAnnotation.EpmTargetTree.MinimumODataProtocolVersion.VersionString(),
                                  version.VersionString()));
                }
            }
        }
예제 #3
0
        /// <summary>
        /// Adds an <see cref="EntityPropertyMappingAttribute"/> for the resource type.
        /// </summary>
        /// <param name="attribute">Given <see cref="EntityPropertyMappingAttribute"/>.</param>
        public void AddEntityPropertyMappingAttribute(EntityPropertyMappingAttribute attribute)
        {
            ExceptionUtils.CheckArgumentNotNull(attribute, "attribute");

            // EntityPropertyMapping attribute can not be added to readonly resource types.
            this.ThrowIfSealed();

            if (this.ResourceTypeKind != ResourceTypeKind.EntityType)
            {
                throw new InvalidOperationException(Strings.ResourceType_EpmOnlyAllowedOnEntityTypes(this.Name));
            }

            // Initialize the EPM annotation for this type
            EpmResourceTypeAnnotation epm = this.Epm();

            if (epm == null)
            {
                epm = new EpmResourceTypeAnnotation();
                this.SetAnnotation(epm);
            }

            // And add the attribute to it
            epm.OwnEpmAttributes.Add(attribute);
        }
예제 #4
0
        /// <summary>
        /// This method is called only when the Properties property is called and the type is already set to read-only.
        /// This method validates all the properties w.r.t to the base type and calls SetReadOnly on all the properties.
        /// </summary>
        private void ValidateType()
        {
            Debug.Assert(this.isLoadPropertiesMethodCalled && this.IsReadOnly, "This method must be invoked only if LoadPropertiesDeclaredOnThisType has been called and the type is set to ReadOnly");

            if (this.BaseType != null)
            {
                // make sure that there are no properties with the same name. Properties with duplicate name within the type
                // is already checked in AddProperty method
                foreach (ResourceProperty rp in this.BaseType.Properties)
                {
                    if (this.propertiesDeclaredOnThisType.Where(p => p.Name == rp.Name).FirstOrDefault() != null)
                    {
                        throw new InvalidOperationException(Strings.ResourceType_PropertyWithSameNameAlreadyExists(rp.Name, this.FullName));
                    }
                }
            }
            else if (this.ResourceTypeKind == ResourceTypeKind.EntityType)
            {
                if (this.propertiesDeclaredOnThisType.Where(p => p.IsOfKind(ResourcePropertyKind.Key)).FirstOrDefault() == null)
                {
                    throw new InvalidOperationException(Strings.ResourceType_MissingKeyPropertiesForEntity(this.FullName));
                }
            }

            // set all the properties to readonly
            foreach (ResourceProperty p in this.propertiesDeclaredOnThisType)
            {
                p.SetReadOnly();

                // Note that we cache the propertyinfo objects for each CLR properties in the ResourceType class
                // rather than the ResourceProperty class because the same ResourceProperty instance can be added
                // to multiple ResourceType instances.
                if (p.CanReflectOnInstanceTypeProperty)
                {
                    // TODO: WCF DS will need to do this close to this place. Probably we will need an internal hook here
                    //   for this reason.
                    // this.GetPropertyInfoDecaredOnThisType(p);
                }
            }

            // Resolve EpmInfos now that everything in the type hierarchy is readonly
            try
            {
                if (!this.epmInfoInitialized)
                {
                    EpmResourceTypeAnnotation.BuildEpm(this);
                    this.MarkEpmInfoInitialized();
                }
            }
            catch
            {
                // If an exception was thrown from this.BuildDynamicEpmInfo(this) method
                // EpmSourceTree and EpmTargetTree may be only half constructed and need to be reset.
                EpmResourceTypeAnnotation epm = this.Epm();
                if (epm != null && !this.epmInfoInitialized)
                {
                    epm.Reset();
                }

                throw;
            }
        }