/// <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(); } }
/// <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())); } } }
/// <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); }
/// <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; } }