Esempio n. 1
0
        /// <summary>
        /// Tries to convert the given value into an instance of <see cref="ODataValue"/>.
        /// </summary>
        /// <param name="property">The property being converted.</param>
        /// <param name="propertyValue">The property value to convert..</param>
        /// <param name="serverTypeName">The server type name of the entity whose properties are being populated.</param>
        /// <param name="visitedComplexTypeObjects">Set of instances of complex types encountered in the hierarchy. Used to detect cycles.</param>
        /// <param name="odataValue">The odata value if one was created.</param>
        /// <returns>Whether or not the value was converted.</returns>
        private bool TryConvertPropertyValue(ClientPropertyAnnotation property, object propertyValue, string serverTypeName, HashSet <object> visitedComplexTypeObjects, out ODataValue odataValue)
        {
            if (property.IsKnownType)
            {
                odataValue = CreateODataPrimitivePropertyValue(property, propertyValue);
                return(true);
            }

            if (property.IsEnumType)
            {
                string enumValue;
                if (propertyValue == null)
                {
                    enumValue = null;
                }
                else
                {
                    enumValue = ClientTypeUtil.GetEnumValuesString(propertyValue.ToString(), property.PropertyType);
                }

                string typeNameInMetadata = this.requestInfo.ResolveNameFromType(property.PropertyType);
                odataValue = new ODataEnumValue(enumValue, typeNameInMetadata);
                return(true);
            }

            if (property.IsPrimitiveOrEnumOrComplexCollection)
            {
                odataValue = this.CreateODataCollectionPropertyValue(property, propertyValue, serverTypeName, visitedComplexTypeObjects);
                return(true);
            }

            odataValue = null;
            return(false);
        }
Esempio n. 2
0
 /// <summary>
 /// Returns the value of the collection property.
 /// </summary>
 /// <param name="property">Collection property details. Must not be null.</param>
 /// <param name="propertyValue">Collection instance.</param>
 /// <param name="visitedComplexTypeObjects">List of instances of complex types encountered in the hierarchy. Used to detect cycles.</param>
 /// <returns>An instance of ODataCollectionValue representing the value of the property.</returns>
 private ODataCollectionValue CreateODataCollectionPropertyValue(ClientPropertyAnnotation property, object propertyValue, HashSet <object> visitedComplexTypeObjects)
 {
     Debug.Assert(property != null, "property != null");
     Debug.Assert(property.IsPrimitiveOrComplexCollection, "This method is supposed to be used only for writing collections");
     Debug.Assert(property.PropertyName != null, "property.PropertyName != null");
     return(this.CreateODataCollection(property.PrimitiveOrComplexCollectionItemType, property.PropertyName, propertyValue, visitedComplexTypeObjects));
 }
Esempio n. 3
0
        private static ClientTypeAnnotation GetPropertyType(ClientTypeAnnotation clientType, string propertyName)
        {
            ClientPropertyAnnotation property = clientType.GetProperty(propertyName, true);

            if (property == null)
            {
                throw System.Data.Services.Client.Error.InvalidOperation(System.Data.Services.Client.Strings.EpmSourceTree_InaccessiblePropertyOnType(propertyName, clientType.ElementTypeName));
            }
            if (property.IsStreamLinkProperty)
            {
                throw System.Data.Services.Client.Error.InvalidOperation(System.Data.Services.Client.Strings.EpmSourceTree_NamedStreamCannotBeMapped(propertyName, clientType.ElementTypeName));
            }
            if (property.IsSpatialType)
            {
                throw System.Data.Services.Client.Error.InvalidOperation(System.Data.Services.Client.Strings.EpmSourceTree_SpatialTypeCannotBeMapped(propertyName, clientType.ElementTypeName));
            }
            if (property.IsPrimitiveOrComplexCollection)
            {
                throw System.Data.Services.Client.Error.InvalidOperation(System.Data.Services.Client.Strings.EpmSourceTree_CollectionPropertyCannotBeMapped(propertyName, clientType.ElementTypeName));
            }
            ClientEdmModel model           = ClientEdmModel.GetModel(clientType.MaxProtocolVersion);
            IEdmType       orCreateEdmType = model.GetOrCreateEdmType(property.PropertyType);

            return(model.GetClientTypeAnnotation(orCreateEdmType));
        }
Esempio n. 4
0
        /// <summary>
        /// Check if this type represents an ATOM-style media link entry and
        /// if so mark the ClientType as such
        /// </summary>
        private void CheckMediaLinkEntry()
        {
            this.isMediaLinkEntry = false;

            // MediaEntryAttribute does not allow multiples, so there can be at most 1 instance on the type.
            MediaEntryAttribute mediaEntryAttribute = (MediaEntryAttribute)this.ElementType.GetCustomAttributes(typeof(MediaEntryAttribute), true).SingleOrDefault();
            if (mediaEntryAttribute != null)
            {
                this.isMediaLinkEntry = true;

                ClientPropertyAnnotation mediaProperty = this.Properties().SingleOrDefault(p => p.PropertyName == mediaEntryAttribute.MediaMemberName);
                if (mediaProperty == null)
                {
#if OPENSILVER
                    throw System.Data.Services.Client.Error.InvalidOperation(System.Data.Services.Client.Strings.ClientType_MissingMediaEntryProperty(
                        this.ElementTypeName, mediaEntryAttribute.MediaMemberName));
#else
                    throw Microsoft.OData.Client.Error.InvalidOperation(Microsoft.OData.Client.Strings.ClientType_MissingMediaEntryProperty(
                        this.ElementTypeName, mediaEntryAttribute.MediaMemberName));
#endif
                }

                this.mediaDataMember = mediaProperty;
            }

            // HasStreamAttribute does not allow multiples, so there can be at most 1 instance on the type.
            bool hasStreamAttribute = this.ElementType.GetCustomAttributes(typeof(HasStreamAttribute), true).Any();
            if (hasStreamAttribute)
            {
                this.isMediaLinkEntry = true;
            }
        }
Esempio n. 5
0
        /// <summary>
        /// Computes the metadata version of the property.
        /// </summary>
        /// <param name="propertyCollection">List of properties for which metadata version needs to be computed.</param>
        /// <param name="visitedComplexTypes">List of complex type already visited.</param>
        /// <returns>the metadata version of the property collection.</returns>
        private Version ComputeVersionForPropertyCollection(IEnumerable<IEdmProperty> propertyCollection, HashSet<IEdmType> visitedComplexTypes)
        {
            Version propertyMetadataVersion = Util.ODataVersion4;

            foreach (IEdmProperty property in propertyCollection)
            {
                ClientPropertyAnnotation propertyAnnotation = this.model.GetClientPropertyAnnotation(property);

                if (property.Type.TypeKind() == EdmTypeKind.Complex && !propertyAnnotation.IsDictionary)
                {
                    if (visitedComplexTypes == null)
                    {
                        visitedComplexTypes = new HashSet<IEdmType>(EqualityComparer<IEdmType>.Default);
                    }
                    else if (visitedComplexTypes.Contains(property.Type.Definition))
                    {
                        continue;
                    }

                    visitedComplexTypes.Add(property.Type.Definition);

                    WebUtil.RaiseVersion(ref propertyMetadataVersion, this.ComputeVersionForPropertyCollection(this.model.GetClientTypeAnnotation(property).EdmProperties(), visitedComplexTypes));
                }
            }

            return propertyMetadataVersion;
        }
Esempio n. 6
0
        internal static void ValidatePropertyMatch(ClientPropertyAnnotation property, ODataProperty atomProperty, ResponseInfo responseInfo, bool performEntityCheck)
        {
            ODataFeed  feed  = atomProperty.Value as ODataFeed;
            ODataEntry entry = atomProperty.Value as ODataEntry;

            if (property.IsKnownType && ((feed != null) || (entry != null)))
            {
                throw System.Data.Services.Client.Error.InvalidOperation(System.Data.Services.Client.Strings.Deserialize_MismatchAtomLinkLocalSimple);
            }
            Type t = null;

            if (feed != null)
            {
                if (!property.IsEntityCollection)
                {
                    throw System.Data.Services.Client.Error.InvalidOperation(System.Data.Services.Client.Strings.Deserialize_MismatchAtomLinkFeedPropertyNotCollection(property.PropertyName));
                }
                t = property.EntityCollectionItemType;
            }
            if (entry != null)
            {
                if (property.IsEntityCollection)
                {
                    throw System.Data.Services.Client.Error.InvalidOperation(System.Data.Services.Client.Strings.Deserialize_MismatchAtomLinkEntryPropertyIsCollection(property.PropertyName));
                }
                t = property.PropertyType;
            }
            if (((t != null) && performEntityCheck) && !ClientTypeUtil.TypeIsEntity(t, responseInfo.MaxProtocolVersion))
            {
                throw System.Data.Services.Client.Error.InvalidOperation(System.Data.Services.Client.Strings.AtomMaterializer_InvalidNonEntityType(t.ToString()));
            }
        }
Esempio n. 7
0
        internal static Type ValidatePropertyMatch(ClientPropertyAnnotation property, ODataNavigationLink link, ResponseInfo responseInfo, bool performEntityCheck)
        {
            Type t = null;

            if (link.IsCollection.HasValue)
            {
                if (link.IsCollection.Value)
                {
                    if (!property.IsEntityCollection)
                    {
                        throw System.Data.Services.Client.Error.InvalidOperation(System.Data.Services.Client.Strings.Deserialize_MismatchAtomLinkFeedPropertyNotCollection(property.PropertyName));
                    }
                    t = property.EntityCollectionItemType;
                }
                else
                {
                    if (property.IsEntityCollection)
                    {
                        throw System.Data.Services.Client.Error.InvalidOperation(System.Data.Services.Client.Strings.Deserialize_MismatchAtomLinkEntryPropertyIsCollection(property.PropertyName));
                    }
                    t = property.PropertyType;
                }
            }
            if (((t != null) && performEntityCheck) && !ClientTypeUtil.TypeIsEntity(t, responseInfo.MaxProtocolVersion))
            {
                throw System.Data.Services.Client.Error.InvalidOperation(System.Data.Services.Client.Strings.AtomMaterializer_InvalidNonEntityType(t.ToString()));
            }
            return(t);
        }
Esempio n. 8
0
        private object GetCollectionInstance(ClientPropertyAnnotation property, out bool instanceCreated)
        {
            instanceCreated = false;
            object obj2 = property.GetValue(this.entity);

            if (obj2 != null)
            {
                return(obj2);
            }
            instanceCreated = true;
            Type propertyType = property.PropertyType;

            if (BindingEntityInfo.IsDataServiceCollection(propertyType, base.RequestInfo.MaxProtocolVersion))
            {
                object[] args = new object[2];
                args[1] = TrackingMode.None;
                return(Activator.CreateInstance(WebUtil.GetDataServiceCollectionOfT(new Type[] { property.EntityCollectionItemType }), args));
            }
            Type c = typeof(List <>).MakeGenericType(new Type[] { property.EntityCollectionItemType });

            if (!propertyType.IsAssignableFrom(c))
            {
                c = propertyType;
            }
            return(Activator.CreateInstance(c));
        }
        /// <summary>
        /// Builds an edm property value from the given annotation.
        /// </summary>
        /// <param name="propertyAnnotation">The property annotation.</param>
        /// <returns>The property value</returns>
        private IEdmPropertyValue BuildEdmPropertyValue(ClientPropertyAnnotation propertyAnnotation)
        {
            var propertyValue = propertyAnnotation.GetValue(this.structuredValue);
            var edmValue      = this.ConvertToEdmValue(propertyValue, propertyAnnotation.EdmProperty.Type);

            return(new EdmPropertyValue(propertyAnnotation.EdmProperty.Name, edmValue));
        }
Esempio n. 10
0
        /// <summary>
        /// Adds a type annotation to the value if it is primitive and not defined on the server.
        /// </summary>
        /// <param name="serverTypeName">The server type name of the entity whose properties are being populated.</param>
        /// <param name="property">The current property.</param>
        /// <param name="odataValue">The already converted value of the property.</param>
        private void AddTypeAnnotationNotDeclaredOnServer(string serverTypeName, ClientPropertyAnnotation property, ODataValue odataValue)
        {
            Debug.Assert(property != null, "property != null");
            Debug.Assert(property.EdmProperty != null, "property.EdmProperty != null");
#if DEBUG
            if (odataValue is ODataCollectionValue)
            {
                Debug.Assert(
                    !this.requestInfo.TypeResolver.ShouldWriteClientTypeForOpenServerProperty(property.EdmProperty, serverTypeName),
                    "Open collection properties are not yet supported. This method will need to be updated when they are.");
            }
#endif
            var primitiveValue = odataValue as ODataPrimitiveValue;
            if (primitiveValue == null)
            {
                return;
            }

            if (!this.requestInfo.Format.UsingAtom &&
                this.requestInfo.TypeResolver.ShouldWriteClientTypeForOpenServerProperty(property.EdmProperty, serverTypeName) &&
                !JsonSharedUtils.ValueTypeMatchesJsonType(primitiveValue, property.EdmProperty.Type.AsPrimitive()))
            {
                // DEVNOTE: it is safe to use the property type name for primitive types because they do not generally support inheritance,
                // and spatial values always contain their specific type inside the GeoJSON/GML representation.
                primitiveValue.SetAnnotation(new SerializationTypeNameAnnotation {
                    TypeName = property.EdmProperty.Type.FullName()
                });
            }
        }
Esempio n. 11
0
        /// <summary>
        /// Returns a client type of the property on the specified resource type.
        /// </summary>
        /// <param name="clientType">The client type to look for the property on.</param>
        /// <param name="propertyName">The name of the property to look for.</param>
        /// <returns>The type of the property specified. Note that for collection properties this returns the type of the item of the collection property.</returns>
        private static ClientTypeAnnotation GetPropertyType(ClientTypeAnnotation clientType, string propertyName)
        {
            Debug.Assert(propertyName != null, "propertyName != null");

            ClientPropertyAnnotation clientProperty = clientType.GetProperty(propertyName, true);

            if (clientProperty == null)
            {
                throw c.Error.InvalidOperation(c.Strings.EpmSourceTree_InaccessiblePropertyOnType(propertyName, clientType.ElementTypeName));
            }

            if (clientProperty.IsStreamLinkProperty)
            {
                throw c.Error.InvalidOperation(c.Strings.EpmSourceTree_NamedStreamCannotBeMapped(propertyName, clientType.ElementTypeName));
            }

            if (clientProperty.IsSpatialType)
            {
                throw c.Error.InvalidOperation(c.Strings.EpmSourceTree_SpatialTypeCannotBeMapped(propertyName, clientType.ElementTypeName));
            }

            if (clientProperty.IsPrimitiveOrComplexCollection)
            {
                throw c.Error.InvalidOperation(c.Strings.EpmSourceTree_CollectionPropertyCannotBeMapped(propertyName, clientType.ElementTypeName));
            }

            ClientEdmModel model    = clientProperty.Model;
            IEdmType       edmType1 = model.GetOrCreateEdmType(clientProperty.PropertyType);
            var            edmType  = edmType1;

            return(model.GetClientTypeAnnotation(edmType));
        }
Esempio n. 12
0
        /// <summary>
        /// Applies the values of a nested <paramref name="feed"/> to the collection
        /// <paramref name="property"/> of the specified <paramref name="entry"/>.
        /// </summary>
        /// <param name="entry">Entry with collection to be modified.</param>
        /// <param name="property">Collection property on the entry.</param>
        /// <param name="feed">Values to apply onto the collection.</param>
        /// <param name="includeLinks">Whether links that are expanded should be materialized.</param>
        private void ApplyFeedToCollection(
            MaterializerEntry entry,
            ClientPropertyAnnotation property,
            ODataResourceSet feed,
            bool includeLinks)
        {
            Debug.Assert(entry.Entry != null, "entry != null");
            Debug.Assert(property != null, "property != null");
            Debug.Assert(feed != null, "feed != null");

            ClientEdmModel       edmModel       = this.MaterializerContext.Model;
            ClientTypeAnnotation collectionType = edmModel.GetClientTypeAnnotation(edmModel.GetOrCreateEdmType(property.ResourceSetItemType));

            IEnumerable <ODataResource> entries = MaterializerFeed.GetFeed(feed).Entries;

            foreach (ODataResource feedEntry in entries)
            {
                this.Materialize(MaterializerEntry.GetEntry(feedEntry), collectionType.ElementType, includeLinks);
            }

            ProjectionPlan continuationPlan = includeLinks ?
                                              ODataEntityMaterializer.CreatePlanForDirectMaterialization(property.ResourceSetItemType) :
                                              ODataEntityMaterializer.CreatePlanForShallowMaterialization(property.ResourceSetItemType);

            this.ApplyItemsToCollection(
                entry,
                property,
                entries.Select(e => MaterializerEntry.GetEntry(e).ResolvedObject),
                feed.NextPageLink,
                continuationPlan,
                false);
        }
Esempio n. 13
0
        internal static object ProjectionInitializeEntity(ODataEntityMaterializer materializer, MaterializerEntry entry, Type expectedType, Type resultType, string[] properties, Func <object, object, Type, object>[] propertyValues)
        {
            if (entry.Entry == null)
            {
                throw new NullReferenceException(System.Data.Services.Client.Strings.AtomMaterializer_EntryToInitializeIsNull(resultType.FullName));
            }
            if (!entry.EntityHasBeenResolved)
            {
                ProjectionEnsureEntryAvailableOfType(materializer, entry, resultType);
            }
            else if (!resultType.IsAssignableFrom(entry.ActualType.ElementType))
            {
                throw new InvalidOperationException(System.Data.Services.Client.Strings.AtomMaterializer_ProjectEntityTypeMismatch(resultType.FullName, entry.ActualType.ElementType.FullName, entry.Entry.Id));
            }
            object resolvedObject = entry.ResolvedObject;

            for (int i = 0; i < properties.Length; i++)
            {
                StreamDescriptor         descriptor;
                string                   propertyName = properties[i];
                ClientPropertyAnnotation annotation   = entry.ActualType.GetProperty(propertyName, materializer.ResponseInfo.IgnoreMissingProperties);
                object                   target       = propertyValues[i](materializer, entry.Entry, expectedType);
                ODataProperty            property     = (from p in entry.Entry.Properties
                                                         where p.Name == propertyName
                                                         select p).FirstOrDefault <ODataProperty>();
                if ((((((property == null) && (entry.NavigationLinks != null)) ? (from l in entry.NavigationLinks
                                                                                  where l.Name == propertyName
                                                                                  select l).FirstOrDefault <ODataNavigationLink>() : null) != null) || (property != null)) || entry.EntityDescriptor.TryGetNamedStreamInfo(propertyName, out descriptor))
                {
                    if (entry.ShouldUpdateFromPayload && (annotation.EdmProperty.Type.TypeKind() == EdmTypeKind.Entity))
                    {
                        materializer.Log.SetLink(entry, annotation.PropertyName, target);
                    }
                    if (entry.ShouldUpdateFromPayload)
                    {
                        if (!annotation.IsEntityCollection)
                        {
                            if (!annotation.IsPrimitiveOrComplexCollection)
                            {
                                annotation.SetValue(resolvedObject, target, annotation.PropertyName, false);
                            }
                        }
                        else
                        {
                            IEnumerable list = (IEnumerable)target;
                            DataServiceQueryContinuation continuation = materializer.nextLinkTable[list];
                            Uri            nextLink = (continuation == null) ? null : continuation.NextLinkUri;
                            ProjectionPlan plan     = (continuation == null) ? null : continuation.Plan;
                            materializer.MergeLists(entry, annotation, list, nextLink, plan);
                        }
                    }
                    else if (annotation.IsEntityCollection)
                    {
                        materializer.FoundNextLinkForUnmodifiedCollection(annotation.GetValue(entry.ResolvedObject) as IEnumerable);
                    }
                }
            }
            return(resolvedObject);
        }
Esempio n. 14
0
        /// <summary>
        /// Returns the value of the complex property.
        /// </summary>
        /// <param name="property">Property which contains name, type, is key (if false and null value, will throw).</param>
        /// <param name="propertyValue">property value</param>
        /// <param name="visitedComplexTypeObjects">List of instances of complex types encountered in the hierarchy. Used to detect cycles.</param>
        /// <returns>An instance of ODataComplexValue containing the value of the properties of the given complex type.</returns>
        private ODataComplexValue CreateODataComplexPropertyValue(ClientPropertyAnnotation property, object propertyValue, HashSet <object> visitedComplexTypeObjects)
        {
            Debug.Assert(propertyValue != null || !property.IsPrimitiveOrComplexCollection, "Collection items must not be null");

            Type propertyType = property.IsPrimitiveOrComplexCollection ? property.PrimitiveOrComplexCollectionItemType : property.PropertyType;

            return(this.CreateODataComplexValue(propertyType, propertyValue, property.PropertyName, property.IsPrimitiveOrComplexCollection, visitedComplexTypeObjects));
        }
Esempio n. 15
0
        /// <summary>
        /// Gets or creates a collection property on the specified <paramref name="instance"/>.
        /// </summary>
        /// <param name="instance">Instance on which to get/create the collection.</param>
        /// <param name="property">Collection property on the <paramref name="instance"/>.</param>
        /// <param name="forLoadProperty">Is this collection being created for LoadProperty scenario.</param>
        /// <returns>
        /// The collection corresponding to the specified <paramref name="property"/>;
        /// never null.
        /// </returns>
        private object GetOrCreateCollectionProperty(object instance, ClientPropertyAnnotation property, bool forLoadProperty)
        {
            Debug.Assert(instance != null, "instance != null");
            Debug.Assert(property != null, "property != null");
            Debug.Assert(property.IsResourceSet, "property.IsEntityCollection has to be true - otherwise property isn't a collection");

            // NOTE: in V1, we would have instantiated nested objects before setting them.
            object result;

            result = property.GetValue(instance);

            if (result == null)
            {
                Type collectionType = property.PropertyType;

                // For backward compatibility we need to have different strategy of collection creation b/w
                // LoadProperty scenario versus regular collection creation scenario.
                if (forLoadProperty)
                {
                    if (BindingEntityInfo.IsDataServiceCollection(collectionType, this.MaterializerContext.Model))
                    {
                        Debug.Assert(WebUtil.GetDataServiceCollectionOfT(property.EntityCollectionItemType) != null, "DataServiceCollection<> must be available here.");

                        // new DataServiceCollection<property.EntityCollectionItemType>(null, TrackingMode.None)
                        result = Activator.CreateInstance(
                            WebUtil.GetDataServiceCollectionOfT(property.EntityCollectionItemType),
                            null,
                            TrackingMode.None);
                    }
                    else
                    {
                        // Try List<> first because that's what we did in V1/V2, but use the actual property type if it doesn't support List<>
                        Type listCollectionType = typeof(List <>).MakeGenericType(property.EntityCollectionItemType);
                        if (collectionType.IsAssignableFrom(listCollectionType))
                        {
                            collectionType = listCollectionType;
                        }

                        result = Activator.CreateInstance(collectionType);
                    }
                }
                else
                {
                    if (DSClient.PlatformHelper.IsInterface(collectionType))
                    {
                        collectionType = typeof(System.Collections.ObjectModel.Collection <>).MakeGenericType(property.EntityCollectionItemType);
                    }

                    result = this.CreateNewInstance(property.EdmProperty.Type, collectionType);
                }

                // Update the property value on the instance.
                property.SetValue(instance, result, property.PropertyName, false /* add */);
            }

            Debug.Assert(result != null, "result != null -- otherwise GetOrCreateCollectionProperty didn't fall back to creation");
            return(result);
        }
Esempio n. 16
0
        /// <summary>
        /// Returns the value of the collection property.
        /// </summary>
        /// <param name="property">Collection property details. Must not be null.</param>
        /// <param name="propertyValue">Collection instance.</param>
        /// <param name="serverTypeName">The server type name of the entity whose properties are being populated.</param>
        /// <param name="visitedComplexTypeObjects">List of instances of complex types encountered in the hierarchy. Used to detect cycles.</param>
        /// <returns>An instance of ODataCollectionValue representing the value of the property.</returns>
        private ODataCollectionValue CreateODataCollectionPropertyValue(ClientPropertyAnnotation property, object propertyValue, string serverTypeName, HashSet <object> visitedComplexTypeObjects)
        {
            Debug.Assert(property != null, "property != null");
            Debug.Assert(property.IsPrimitiveOrEnumOrComplexCollection, "This method is supposed to be used only for writing collections");
            Debug.Assert(property.PropertyName != null, "property.PropertyName != null");
            bool isDynamic = this.requestInfo.TypeResolver.ShouldWriteClientTypeForOpenServerProperty(property.EdmProperty, serverTypeName);

            return(this.CreateODataCollection(property.PrimitiveOrComplexCollectionItemType, property.PropertyName, propertyValue, visitedComplexTypeObjects, isDynamic));
        }
Esempio n. 17
0
 /// <summary>
 /// Constructs a new instance.
 /// </summary>
 /// <param name="requestInfo">Information about the request.</param>
 /// <param name="mergeOption">Merge option.</param>
 /// <param name="entityDescriptor">Entity whose property is being loaded.</param>
 /// <param name="property">Property which is being loaded.</param>
 internal LoadPropertyResponseInfo(
     RequestInfo requestInfo,
     MergeOption mergeOption,
     EntityDescriptor entityDescriptor,
     ClientPropertyAnnotation property)
     : base(requestInfo, mergeOption)
 {
     this.EntityDescriptor = entityDescriptor;
     this.Property         = property;
 }
Esempio n. 18
0
 public void Initialize()
 {
     this.clientEdmModel = new ClientEdmModel(ODataProtocolVersion.V4);
     this.clientEdmModel.GetOrCreateEdmType(typeof(TestCustomer));
     this.clientEdmModel.GetOrCreateEdmType(typeof(TestOrder));
     this.materializerContext = new TestMaterializerContext()
     {
         Model = this.clientEdmModel
     };
     this.ordersProperty = this.clientEdmModel.GetClientTypeAnnotation(typeof(TestCustomer)).GetProperty("Orders", UndeclaredPropertyBehavior.ThrowException);
 }
Esempio n. 19
0
        /// <summary>
        /// Creates and returns an <see cref="ODataValue"/> for the given primitive value.
        /// </summary>
        /// <param name="property">The property being converted.</param>
        /// <param name="propertyValue">The property value to convert..</param>
        /// <returns>An ODataValue representing the given value.</returns>
        private static ODataValue CreateODataPrimitivePropertyValue(ClientPropertyAnnotation property, object propertyValue)
        {
            if (propertyValue == null)
            {
                return(new ODataNullValue());
            }

            propertyValue = ConvertPrimitiveValueToRecognizedODataType(propertyValue, property.PropertyType);

            return(new ODataPrimitiveValue(propertyValue));
        }
Esempio n. 20
0
 /// <summary>
 /// Determines whether a given property should be serialized into an insert or update payload.
 /// </summary>
 /// <param name="type">The declaring type of the property.</param>
 /// <param name="property">The property.</param>
 /// <returns>Whether or not the property should be serialized.</returns>
 private static bool ShouldSerializeProperty(ClientTypeAnnotation type, ClientPropertyAnnotation property)
 {
     // don't write property if it is a dictionary
     // don't write mime data member or the mime type member for it
     // link properties need to be ignored
     // don't write property if it is tagged with IgnoreClientProperty attribute
     return !property.IsDictionary
         && property != type.MediaDataMember
         && !property.IsStreamLinkProperty
         && (type.MediaDataMember == null || type.MediaDataMember.MimeTypeProperty != property)
         && !property.PropertyInfo.GetCustomAttributes(typeof(IgnoreClientPropertyAttribute)).Any();
 }
Esempio n. 21
0
        /// <summary>
        /// Returns the resource of the complex property.
        /// </summary>
        /// <param name="property">Property which contains name, type, is key (if false and null value, will throw).</param>
        /// <param name="propertyValue">property value</param>
        /// <param name="visitedComplexTypeObjects">List of instances of complex types encountered in the hierarchy. Used to detect cycles.</param>
        /// <returns>An instance of ODataResourceWrapper containing the resource of the properties of the given complex type.</returns>
        private ODataResourceWrapper CreateODataComplexPropertyResource(ClientPropertyAnnotation property, object propertyValue, HashSet <object> visitedComplexTypeObjects)
        {
            Type propertyType = property.IsComplexCollection ? property.PrimitiveOrComplexCollectionItemType : property.PropertyType;

            if (propertyValue != null && propertyType != propertyValue.GetType())
            {
                Debug.Assert(propertyType.IsAssignableFrom(propertyValue.GetType()), "Type from value should equals to or derived from property type from model.");
                propertyType = propertyValue.GetType();
            }

            return(this.CreateODataResourceWrapperForComplex(propertyType, propertyValue, property.PropertyName, visitedComplexTypeObjects));
        }
Esempio n. 22
0
        private MaterializeAtom ReadPropertyFromRawData(ClientPropertyAnnotation property)
        {
            MaterializeAtom    atom;
            DataServiceContext source = (DataServiceContext)base.Source;
            bool applyingChanges      = source.ApplyingChanges;

            try
            {
                source.ApplyingChanges = true;
                string   mime     = null;
                Encoding encoding = null;
                Type     type     = property.EntityCollectionItemType ?? property.NullablePropertyType;
                IList    results  = (IList)Activator.CreateInstance(typeof(List <>).MakeGenericType(new Type[] { type }));
                HttpProcessUtility.ReadContentType(base.ContentType, out mime, out encoding);
                using (Stream stream = base.GetResponseStream())
                {
                    if (property.PropertyType == typeof(byte[]))
                    {
                        int    contentLength = (int)base.ContentLength;
                        byte[] buffer        = null;
                        if (contentLength >= 0)
                        {
                            buffer = ReadByteArrayWithContentLength(stream, contentLength);
                        }
                        else
                        {
                            buffer = ReadByteArrayChunked(stream);
                        }
                        results.Add(buffer);
                        property.SetValue(this.entity, buffer, this.propertyName, false);
                    }
                    else
                    {
                        StreamReader reader = new StreamReader(stream, encoding);
                        object       obj2   = (property.PropertyType == typeof(string)) ? reader.ReadToEnd() : ClientConvert.ChangeType(reader.ReadToEnd(), property.PropertyType);
                        results.Add(obj2);
                        property.SetValue(this.entity, obj2, this.propertyName, false);
                    }
                }
                if (property.MimeTypeProperty != null)
                {
                    property.MimeTypeProperty.SetValue(this.entity, mime, null, false);
                }
                atom = MaterializeAtom.CreateWrapper(source, results);
            }
            finally
            {
                source.ApplyingChanges = applyingChanges;
            }
            return(atom);
        }
Esempio n. 23
0
        private void ApplyFeedToCollection(MaterializerEntry entry, ClientPropertyAnnotation property, ODataFeed feed, bool includeLinks)
        {
            ClientEdmModel           model = ClientEdmModel.GetModel(base.ResponseInfo.MaxProtocolVersion);
            ClientTypeAnnotation     clientTypeAnnotation = model.GetClientTypeAnnotation(model.GetOrCreateEdmType(property.EntityCollectionItemType));
            IEnumerable <ODataEntry> entries = MaterializerFeed.GetFeed(feed).Entries;

            foreach (ODataEntry entry2 in entries)
            {
                this.Materialize(MaterializerEntry.GetEntry(entry2), clientTypeAnnotation.ElementType, includeLinks);
            }
            ProjectionPlan continuationPlan = includeLinks ? CreatePlanForDirectMaterialization(property.EntityCollectionItemType) : CreatePlanForShallowMaterialization(property.EntityCollectionItemType);

            this.ApplyItemsToCollection(entry, property, from e in entries select MaterializerEntry.GetEntry(e).ResolvedObject, feed.NextPageLink, continuationPlan);
        }
Esempio n. 24
0
        /// <summary>
        /// Set instance annotation for a property
        /// </summary>
        /// <param name="propertyName">Property name</param>
        /// <param name="instanceAnnotations">Intance annotations to be set</param>
        /// <param name="type">The type of the containing object</param>
        /// <param name="declaringInstance">The containing object instance</param>
        private void SetInstanceAnnotations(string propertyName, IDictionary <string, object> instanceAnnotations, Type type, object declaringInstance)
        {
            if (declaringInstance != null)
            {
                UndeclaredPropertyBehavior undeclaredPropertyBehavior = this.MaterializerContext.Context.UndeclaredPropertyBehavior;

                // Get the client property info
                ClientEdmModel             edmModel                 = this.MaterializerContext.Model;
                ClientTypeAnnotation       clientTypeAnnotation     = edmModel.GetClientTypeAnnotation(edmModel.GetOrCreateEdmType(type));
                ClientPropertyAnnotation   clientPropertyAnnotation = clientTypeAnnotation.GetProperty(propertyName, undeclaredPropertyBehavior);
                Tuple <object, MemberInfo> annotationKeyForProperty = new Tuple <object, MemberInfo>(declaringInstance, clientPropertyAnnotation.PropertyInfo);
                SetInstanceAnnotations(annotationKeyForProperty, instanceAnnotations);
            }
        }
        /// <summary>
        /// Returns the value of the complex property.
        /// </summary>
        /// <param name="property">Property which contains name, type, is key (if false and null value, will throw).</param>
        /// <param name="propertyValue">property value</param>
        /// <param name="visitedComplexTypeObjects">List of instances of complex types encountered in the hierarchy. Used to detect cycles.</param>
        /// <returns>An instance of ODataComplexValue containing the value of the properties of the given complex type.</returns>
        private ODataComplexValue CreateODataComplexPropertyValue(ClientPropertyAnnotation property, object propertyValue, HashSet <object> visitedComplexTypeObjects)
        {
            Debug.Assert(propertyValue != null || !property.IsPrimitiveOrEnumOrComplexCollection, "Collection items must not be null");

            Type propertyType = property.IsPrimitiveOrEnumOrComplexCollection ? property.PrimitiveOrComplexCollectionItemType : property.PropertyType;

            if (propertyValue != null && propertyType != propertyValue.GetType())
            {
                Debug.Assert(propertyType.IsAssignableFrom(propertyValue.GetType()), "Type from value should equals to or derived from property type from model.");
                propertyType = propertyValue.GetType();
            }

            return(this.CreateODataComplexValue(propertyType, propertyValue, property.PropertyName, property.IsPrimitiveOrEnumOrComplexCollection, visitedComplexTypeObjects));
        }
Esempio n. 26
0
        private void ApplyItemsToCollection(MaterializerEntry entry, ClientPropertyAnnotation property, IEnumerable items, Uri nextLink, ProjectionPlan continuationPlan)
        {
            Func <LinkDescriptor, bool> predicate     = null;
            object               instance             = entry.ShouldUpdateFromPayload ? GetOrCreateCollectionProperty(entry.ResolvedObject, property, null) : null;
            ClientEdmModel       model                = ClientEdmModel.GetModel(base.ResponseInfo.MaxProtocolVersion);
            ClientTypeAnnotation clientTypeAnnotation = model.GetClientTypeAnnotation(model.GetOrCreateEdmType(property.EntityCollectionItemType));

            foreach (object obj3 in items)
            {
                if (!clientTypeAnnotation.ElementType.IsAssignableFrom(obj3.GetType()))
                {
                    throw new InvalidOperationException(System.Data.Services.Client.Strings.AtomMaterializer_EntryIntoCollectionMismatch(obj3.GetType().FullName, clientTypeAnnotation.ElementType.FullName));
                }
                if (entry.ShouldUpdateFromPayload)
                {
                    property.SetValue(instance, obj3, property.PropertyName, true);
                    this.log.AddedLink(entry, property.PropertyName, obj3);
                }
            }
            if (entry.ShouldUpdateFromPayload)
            {
                this.FoundNextLinkForCollection(instance as IEnumerable, nextLink, continuationPlan);
            }
            else
            {
                this.FoundNextLinkForUnmodifiedCollection(property.GetValue(entry.ResolvedObject) as IEnumerable);
            }
            if ((this.mergeOption == MergeOption.OverwriteChanges) || (this.mergeOption == MergeOption.PreserveChanges))
            {
                if (predicate == null)
                {
                    predicate = delegate(LinkDescriptor x) {
                        if (MergeOption.OverwriteChanges != this.mergeOption)
                        {
                            return(EntityStates.Added != x.State);
                        }
                        return(true);
                    };
                }
                foreach (object obj4 in (from x in base.ResponseInfo.EntityTracker.GetLinks(entry.ResolvedObject, property.PropertyName).Where <LinkDescriptor>(predicate) select x.Target).Except <object>(EnumerateAsElementType <object>(items)))
                {
                    if (instance != null)
                    {
                        property.RemoveValue(instance, obj4);
                    }
                    this.log.RemovedLink(entry, property.PropertyName, obj4);
                }
            }
        }
Esempio n. 27
0
        internal Uri GetNavigationLink(UriResolver baseUriResolver, ClientPropertyAnnotation property)
        {
            LinkInfo linkInfo       = null;
            Uri      navigationLink = null;

            if (this.TryGetLinkInfo(property.PropertyName, out linkInfo))
            {
                navigationLink = linkInfo.NavigationLink;
            }
            if (navigationLink == null)
            {
                Uri requestUri = Util.CreateUri(property.PropertyName + (property.IsEntityCollection ? "()" : string.Empty), UriKind.Relative);
                navigationLink = Util.CreateUri(this.GetResourceUri(baseUriResolver, true), requestUri);
            }
            return(navigationLink);
        }
Esempio n. 28
0
 private void MergeLists(MaterializerEntry entry, ClientPropertyAnnotation property, IEnumerable list, Uri nextLink, ProjectionPlan plan)
 {
     if ((entry.ShouldUpdateFromPayload && (property.NullablePropertyType == list.GetType())) && (property.GetValue(entry.ResolvedObject) == null))
     {
         property.SetValue(entry.ResolvedObject, list, property.PropertyName, false);
         this.FoundNextLinkForCollection(list, nextLink, plan);
         foreach (object obj2 in list)
         {
             this.log.AddedLink(entry, property.PropertyName, obj2);
         }
     }
     else
     {
         this.ApplyItemsToCollection(entry, property, list, nextLink, plan);
     }
 }
Esempio n. 29
0
        /// <summary>
        /// Populates the collection property on the entry's resolved object with the given items enumerator.
        /// </summary>
        /// <param name="entry">Entry with collection to be modified.</param>
        /// <param name="property">Collection property on the entry.</param>
        /// <param name="items">Values to apply onto the collection.</param>
        /// <param name="nextLink">Next link for collection continuation.</param>
        /// <param name="continuationPlan">Projection plan for collection continuation.</param>
        /// <returns>Collection instance that was populated.</returns>
        private object PopulateCollectionProperty(
            MaterializerEntry entry,
            ClientPropertyAnnotation property,
            IEnumerable <object> items,
            Uri nextLink,
            ProjectionPlan continuationPlan)
        {
            Debug.Assert(entry.Entry != null || entry.ForLoadProperty, "ODataResource should be non-null except for LoadProperty");
            Debug.Assert(property != null, "property != null");
            Debug.Assert(items != null, "items != null");

            object collection = null;

            ClientEdmModel       edmModel       = this.MaterializerContext.Model;
            ClientTypeAnnotation collectionType = edmModel.GetClientTypeAnnotation(edmModel.GetOrCreateEdmType(property.ResourceSetItemType));

            if (entry.ShouldUpdateFromPayload)
            {
                collection = this.GetOrCreateCollectionProperty(entry.ResolvedObject, property, entry.ForLoadProperty);

                foreach (object item in items)
                {
                    // Validate that item can be inserted into collection.
                    ValidateCollectionElementTypeIsItemType(item.GetType(), collectionType.ElementType);

                    property.SetValue(collection, item, property.PropertyName, true /* allowAdd? */);

                    this.EntityTrackingAdapter.MaterializationLog.AddedLink(entry, property.PropertyName, item);
                }

                this.FoundNextLinkForCollection(collection as IEnumerable, nextLink, continuationPlan);
            }
            else
            {
                Debug.Assert(!entry.ForLoadProperty, "LoadProperty should always have ShouldUpdateForPayload set to true.");

                foreach (object item in items)
                {
                    // Validate that item can be inserted into collection.
                    ValidateCollectionElementTypeIsItemType(item.GetType(), collectionType.ElementType);
                }

                this.FoundNextLinkForUnmodifiedCollection(property.GetValue(entry.ResolvedObject) as IEnumerable);
            }

            return(collection);
        }
Esempio n. 30
0
        /// <summary>
        /// Validates the specified <paramref name="property"/> matches
        /// the parsed <paramref name="atomProperty"/>.
        /// </summary>
        /// <param name="property">Property as understood by the type system.</param>
        /// <param name="atomProperty">Property as parsed.</param>
        /// <param name="model">Client model.</param>
        /// <param name="performEntityCheck">whether to do the entity check or not.</param>
        internal static void ValidatePropertyMatch(ClientPropertyAnnotation property, ODataProperty atomProperty, ClientEdmModel model, bool performEntityCheck)
        {
            Debug.Assert(property != null, "property != null");
            Debug.Assert(atomProperty != null, "atomProperty != null");

            ODataResourceSet feed  = atomProperty.Value as ODataResourceSet;
            ODataResource    entry = atomProperty.Value as ODataResource;

            if (property.IsKnownType && (feed != null || entry != null))
            {
                throw DSClient.Error.InvalidOperation(DSClient.Strings.Deserialize_MismatchAtomLinkLocalSimple);
            }

            Type propertyType = null;

            if (feed != null)
            {
                // We need to fail if the payload states that the property is a navigation collection property
                // and in the client, the property is not a collection property.
                if (!property.IsEntityCollection)
                {
                    throw DSClient.Error.InvalidOperation(DSClient.Strings.Deserialize_MismatchAtomLinkFeedPropertyNotCollection(property.PropertyName));
                }

                propertyType = property.EntityCollectionItemType;
            }

            if (entry != null)
            {
                if (property.IsEntityCollection)
                {
                    throw DSClient.Error.InvalidOperation(DSClient.Strings.Deserialize_MismatchAtomLinkEntryPropertyIsCollection(property.PropertyName));
                }

                propertyType = property.PropertyType;
            }

            // If the server type and the client type does not match, we need to throw.
            // This is a breaking change from V1/V2 where we allowed materialization of entities into non-entities and vice versa
            if (propertyType != null && performEntityCheck)
            {
                if (!ClientTypeUtil.TypeIsEntity(propertyType, model))
                {
                    throw DSClient.Error.InvalidOperation(DSClient.Strings.AtomMaterializer_InvalidNonEntityType(propertyType.ToString()));
                }
            }
        }