/// <summary> /// Initializes the epm fields and builds the information into the fields /// </summary> private void InitializeAndBuildTree() { lock (this.epmDataLock) { if (!this.EpmNeedsInitializing) { // already done return; } // work on local objects so we don't set the fields and start handing out // unbuilt trees System.Data.Services.Client.Serializers.EpmTargetTree localEpmTargetTree = new System.Data.Services.Client.Serializers.EpmTargetTree(); System.Data.Services.Client.Serializers.EpmSourceTree localEpmSourceTree = new System.Data.Services.Client.Serializers.EpmSourceTree(localEpmTargetTree); BuildEpmInfo(this.clientTypeAnnotation, localEpmSourceTree); localEpmSourceTree.Validate(this.clientTypeAnnotation); localEpmTargetTree.Validate(); // now that we are all built we can set the real fields and hand them out this.epmTargetTree = localEpmTargetTree; this.epmSourceTree = localEpmSourceTree; } }
/// <summary> /// By going over EntityPropertyMappingInfoAttribute(s) defined on <paramref name="type"/> /// builds the corresponding EntityPropertyMappingInfo /// </summary> /// <param name="type">Type being looked at</param> /// <param name="clientTypeAnnotation">The ClientTypeAnnotation to refer to</param> /// <param name="sourceTree">The source tree to populate.</param> private static void BuildEpmInfo(Type type, ClientTypeAnnotation clientTypeAnnotation, System.Data.Services.Client.Serializers.EpmSourceTree sourceTree) { // EPM is only allowed on entity types. Note that we can't throw now if the EPM attribute is on a complex type since we didn't throw when we ship V2. if (clientTypeAnnotation.IsEntityType) { Type baseType = c.PlatformHelper.GetBaseType(type); ClientTypeAnnotation baseClientTypeAnnotation = null; ClientEdmModel clientEdmModel = clientTypeAnnotation.model; ODataEntityPropertyMappingCollection mappings = null; if (baseType != null && baseType != typeof(object)) { // have CLR base type if (((EdmStructuredType)clientTypeAnnotation.EdmType).BaseType == null) { // CLR base type is not an entity type - append its EPM onto the current type annotation BuildEpmInfo(baseType, clientTypeAnnotation, sourceTree); // we should not create a new mapping in this case mappings = clientEdmModel.GetAnnotationValue <ODataEntityPropertyMappingCollection>(clientTypeAnnotation.EdmType); } else { // CLR base type is an entity type, build EPM onto the base type annotation baseClientTypeAnnotation = clientEdmModel.GetClientTypeAnnotation(baseType); BuildEpmInfo(baseType, baseClientTypeAnnotation, sourceTree); } } foreach (EntityPropertyMappingAttribute epmAttr in type.GetCustomAttributes(typeof(EntityPropertyMappingAttribute), false)) { BuildEpmInfo(epmAttr, type, clientTypeAnnotation, sourceTree); // Add these mappings to the ODataEntityPropertyMapping class so that // ODataLib can consume them if (mappings == null) { mappings = new ODataEntityPropertyMappingCollection(); } mappings.Add(epmAttr); } if (mappings != null) { ODataEntityPropertyMappingCollection oldMappings = clientEdmModel.GetAnnotationValue <ODataEntityPropertyMappingCollection>(clientTypeAnnotation.EdmType); if (oldMappings != null) { List <EntityPropertyMappingAttribute> exclusiveMappings = oldMappings.Where(oldM => !mappings.Any(newM => oldM.SourcePath == newM.SourcePath)).ToList(); foreach (EntityPropertyMappingAttribute epmAttr in exclusiveMappings) { mappings.Add(epmAttr); } } clientEdmModel.SetAnnotationValue(clientTypeAnnotation.EdmType, mappings); } } }
/// <summary> /// Builds the EntityPropertyMappingInfo corresponding to an EntityPropertyMappingAttribute, also builds the delegate to /// be invoked in order to retrieve the property provided in the <paramref name="epmAttr"/> /// </summary> /// <param name="epmAttr">Source EntityPropertyMappingAttribute</param> /// <param name="definingType">ResourceType on which to look for the property</param> /// <param name="clientTypeAnnotation">The ClientTypeAnnotation to refer to</param> /// <param name="sourceTree">The source tree to populate.</param> private static void BuildEpmInfo(EntityPropertyMappingAttribute epmAttr, Type definingType, ClientTypeAnnotation clientTypeAnnotation, System.Data.Services.Client.Serializers.EpmSourceTree sourceTree) { sourceTree.Add(new System.Data.Services.Client.Serializers.EntityPropertyMappingInfo(epmAttr, definingType, clientTypeAnnotation)); }
/// <summary> /// By going over EntityPropertyMappingInfoAttribute(s) defined on the ElementType /// builds the corresponding EntityPropertyMappingInfo /// </summary> /// <param name="clientTypeAnnotation">The ClientTypeAnnotation to refer to</param> /// <param name="sourceTree">The source tree to populate.</param> /// <remarks>This method should be called after all properties are set on the edm type.</remarks> private static void BuildEpmInfo(ClientTypeAnnotation clientTypeAnnotation, System.Data.Services.Client.Serializers.EpmSourceTree sourceTree) { BuildEpmInfo(clientTypeAnnotation.ElementType, clientTypeAnnotation, sourceTree); }