/// <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); }
/// <summary>Runs this plan.</summary> /// <param name="materializer">Materializer under which materialization should happen.</param> /// <param name="entry">Root entry to materialize.</param> /// <param name="expectedType">Expected type for the <paramref name="entry"/>.</param> /// <returns>The materialized object.</returns> internal object Run(ODataEntityMaterializer materializer, ODataResource entry, Type expectedType) { Debug.Assert(materializer != null, "materializer != null"); Debug.Assert(entry != null, "entry != null"); return(this.Plan(materializer, entry, expectedType)); }
/// <summary>Runs this plan.</summary> /// <param name="materializer">Materializer under which materialization should happen.</param> /// <param name="entry">Root entry to materialize.</param> /// <param name="expectedType">Expected type for the <paramref name="entry"/>.</param> /// <returns>The materialized object.</returns> internal object Run(ODataEntityMaterializer materializer, ODataEntry entry, Type expectedType) { Debug.Assert(materializer != null, "materializer != null"); Debug.Assert(entry != null, "entry != null"); return this.Plan(materializer, entry, expectedType); }
/// <summary>Checks whether the entity on the specified <paramref name="path"/> is null.</summary> /// <param name="entry">Root entry for paths.</param> /// <param name="expectedType">Expected type for <paramref name="entry"/>.</param> /// <param name="path">Path to pull value for.</param> /// <returns>Whether the specified <paramref name="path"/> is null.</returns> /// <remarks> /// This method will not instantiate entity types on the path. /// </remarks> internal static bool ProjectionCheckValueForPathIsNull( object entry, Type expectedType, object path) { Debug.Assert(entry.GetType() == typeof(ODataEntry), "entry.GetType() == typeof(ODataEntry)"); Debug.Assert(path.GetType() == typeof(ProjectionPath), "path.GetType() == typeof(ProjectionPath)"); return(ODataEntityMaterializer.ProjectionCheckValueForPathIsNull(MaterializerEntry.GetEntry((ODataEntry)entry), expectedType, (ProjectionPath)path)); }
/// <summary>Initializes a projection-driven entry (with a specific type and specific properties).</summary> /// <param name="materializer">Materializer under which projection is taking place.</param> /// <param name="entry">Root entry for paths.</param> /// <param name="expectedType">Expected type for <paramref name="entry"/>.</param> /// <param name="resultType">Expected result type.</param> /// <param name="properties">Properties to materialize.</param> /// <param name="propertyValues">Functions to get values for functions.</param> /// <returns>The initialized entry.</returns> internal static object ProjectionInitializeEntity( object materializer, object entry, Type expectedType, Type resultType, string[] properties, Func <object, object, Type, object>[] propertyValues) { Debug.Assert(typeof(ODataEntityMaterializer).IsAssignableFrom(materializer.GetType()), "typeof(ODataEntityMaterializer).IsAssignableFrom(materializer.GetType())"); Debug.Assert(entry.GetType() == typeof(ODataEntry), "entry.GetType() == typeof(ODataEntry)"); return(ODataEntityMaterializer.ProjectionInitializeEntity((ODataEntityMaterializer)materializer, MaterializerEntry.GetEntry((ODataEntry)entry), expectedType, resultType, properties, propertyValues)); }
/// <summary>Provides support for Select invocations for projections.</summary> /// <param name="materializer">Materializer under which projection is taking place.</param> /// <param name="entry">Root entry for paths.</param> /// <param name="expectedType">Expected type for <paramref name="entry"/>.</param> /// <param name="resultType">Expected result type.</param> /// <param name="path">Path to traverse.</param> /// <param name="selector">Selector callback.</param> /// <returns>An enumerable with the select results.</returns> internal static IEnumerable ProjectionSelect( object materializer, object entry, Type expectedType, Type resultType, object path, Func <object, object, Type, object> selector) { Debug.Assert(typeof(ODataEntityMaterializer).IsAssignableFrom(materializer.GetType()), "typeof(ODataEntityMaterializer).IsAssignableFrom(materializer.GetType())"); Debug.Assert(entry.GetType() == typeof(ODataEntry), "entry.GetType() == typeof(ODataEntry)"); Debug.Assert(path.GetType() == typeof(ProjectionPath), "path.GetType() == typeof(ProjectionPath)"); return(ODataEntityMaterializer.ProjectionSelect((ODataEntityMaterializer)materializer, MaterializerEntry.GetEntry((ODataEntry)entry), expectedType, resultType, (ProjectionPath)path, selector)); }
/// <summary>Provides support for getting payload entries during projections.</summary> /// <param name="entry">Entry to get sub-entry from.</param> /// <param name="name">Name of sub-entry.</param> /// <returns>The sub-entry (never null).</returns> internal static object ProjectionGetEntry(object entry, string name) { Debug.Assert(entry.GetType() == typeof(ODataEntry), "entry.GetType() == typeof(ODataEntry)"); return(ODataEntityMaterializer.ProjectionGetEntry(MaterializerEntry.GetEntry((ODataEntry)entry), name)); }
/// <summary>Creates a list to a target element type.</summary> /// <param name="materializer">Materializer used to flow link tracking.</param> /// <typeparam name="T">Element type to enumerate over.</typeparam> /// <typeparam name="TTarget">Element type for list.</typeparam> /// <param name="source">Element source.</param> /// <returns> /// An IEnumerable<T> that iterates over the specified <paramref name="source"/>. /// </returns> /// <remarks> /// This method should be unnecessary with .NET 4.0 covariance support. /// </remarks> internal static List <TTarget> ListAsElementType <T, TTarget>(object materializer, IEnumerable <T> source) where T : TTarget { Debug.Assert(typeof(ODataEntityMaterializer).IsAssignableFrom(materializer.GetType()), "typeof(ODataEntityMaterializer).IsAssignableFrom(materializer.GetType())"); return(ODataEntityMaterializer.ListAsElementType <T, TTarget>((ODataEntityMaterializer)materializer, source)); }
/// <summary>Enumerates casting each element to a type.</summary> /// <typeparam name="T">Element type to enumerate over.</typeparam> /// <param name="source">Element source.</param> /// <returns> /// An IEnumerable<T> that iterates over the specified <paramref name="source"/>. /// </returns> /// <remarks> /// This method should be unnecessary with .NET 4.0 covariance support. /// </remarks> internal static IEnumerable <T> EnumerateAsElementType <T>(IEnumerable source) { return(ODataEntityMaterializer.EnumerateAsElementType <T>(source)); }
/// <summary>Materializes an entry without including in-lined expanded links.</summary> /// <param name="materializer">Materializer under which materialization should take place.</param> /// <param name="entry">Entry with object to materialize.</param> /// <param name="expectedEntryType">Expected type for the entry.</param> /// <returns>The materialized instance.</returns> internal static object ShallowMaterializePlan(object materializer, object entry, Type expectedEntryType) { Debug.Assert(typeof(ODataEntityMaterializer).IsAssignableFrom(materializer.GetType()), "typeof(ODataEntityMaterializer).IsAssignableFrom(materializer.GetType())"); Debug.Assert(entry.GetType() == typeof(ODataEntry), "entry.GetType() == typeof(ODataEntry)"); return(ODataEntityMaterializer.ShallowMaterializePlan((ODataEntityMaterializer)materializer, MaterializerEntry.GetEntry((ODataEntry)entry), expectedEntryType)); }
/// <summary> /// Applies the values of the <paramref name="items"/> enumeration to the /// <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="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> /// <param name="isContinuation">Whether this is a continuation request.</param> internal void ApplyItemsToCollection( MaterializerEntry entry, ClientPropertyAnnotation property, IEnumerable items, Uri nextLink, ProjectionPlan continuationPlan, bool isContinuation) { 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"); IEnumerable <object> itemsEnumerable = ODataEntityMaterializer.EnumerateAsElementType <object>(items); // Populate the collection property with items collection. object collection = this.PopulateCollectionProperty(entry, property, itemsEnumerable, nextLink, continuationPlan); // Get collection of all non-linked elements in collection and remove them except for the ones that were obtained from the response. if (this.EntityTrackingAdapter.MergeOption == MergeOption.OverwriteChanges || this.EntityTrackingAdapter.MergeOption == MergeOption.PreserveChanges) { var linkedItemsInCollection = this.EntityTrackingAdapter .EntityTracker .GetLinks(entry.ResolvedObject, property.PropertyName) .Select(l => new { l.Target, l.IsModified }); if (collection != null && !property.IsDictionary) { var nonLinkedNonReceivedItemsInCollection = ODataEntityMaterializer.EnumerateAsElementType <object>((IEnumerable)collection) .Except(linkedItemsInCollection.Select(i => i.Target)) .Except(itemsEnumerable).ToArray(); // Since no link exists, we just remove the item from the collection foreach (var item in nonLinkedNonReceivedItemsInCollection) { property.RemoveValue(collection, item); } } // When the first time a property or collection is being loaded, we remove all items other than the ones that we receive. if (!isContinuation) { IEnumerable <object> itemsToRemove; if (this.EntityTrackingAdapter.MergeOption == MergeOption.OverwriteChanges) { itemsToRemove = linkedItemsInCollection.Select(i => i.Target); } else { Debug.Assert( this.EntityTrackingAdapter.MergeOption == MergeOption.PreserveChanges, "this.EntityTrackingAdapter.MergeOption == MergeOption.PreserveChanges"); itemsToRemove = linkedItemsInCollection .Where(i => !i.IsModified) .Select(i => i.Target); } itemsToRemove = itemsToRemove.Except(itemsEnumerable); foreach (var item in itemsToRemove) { if (collection != null) { property.RemoveValue(collection, item); } this.EntityTrackingAdapter.MaterializationLog.RemovedLink(entry, property.PropertyName, item); } } } }
internal object Run(ODataEntityMaterializer materializer, ODataEntry entry, Type expectedType) { return(this.Plan(materializer, entry, expectedType)); }
internal object Run(ODataEntityMaterializer materializer, ODataEntry entry, Type expectedType) { return this.Plan(materializer, entry, expectedType); }