Пример #1
0
        /// <summary>Materializes the specified <paramref name="entry"/> as dynamic property.</summary>
        /// <param name="entry">Entry with object to materialize.</param>
        /// <param name="link">Nested resource link as parsed.</param>
        private void MaterializeDynamicProperty(MaterializerEntry entry, ODataNestedResourceInfo link)
        {
            Debug.Assert(entry != null, "entry != null");
            Debug.Assert(entry.ResolvedObject != null, "entry.ResolvedObject != null -- otherwise not resolved/created!");
            Debug.Assert(link != null, "link != null");

            ClientEdmModel model = this.MaterializerContext.Model;

            IDictionary <string, object> containerProperty;

            // Stop if owning type is not an open type
            // Or container property is not found
            // Or key with matching name already exists in the dictionary
            if (!ClientTypeUtil.IsInstanceOfOpenType(entry.ResolvedObject, model) ||
                !ClientTypeUtil.TryGetContainerProperty(entry.ResolvedObject, out containerProperty) ||
                containerProperty.ContainsKey(link.Name))
            {
                return;
            }

            MaterializerNavigationLink linkState = MaterializerNavigationLink.GetLink(link);

            if (linkState == null || (linkState.Entry == null && linkState.Feed == null))
            {
                return;
            }

            // NOTE: ODL (and OData WebApi) support navigational property on complex types
            // That support has not yet been implemented in OData client

            // An entity or entity collection as a dynamic property currently doesn't work as expected
            // due to the absence of a navigational property definition in the metadata
            // to express the relationship between that entity and the parent entity - unless they're the same type!
            // Only materialize a nested resource if its a complex or complex collection

            if (linkState.Feed != null)
            {
                string collectionTypeName     = linkState.Feed.TypeName; // TypeName represents a collection e.g. Collection(NS.Type)
                string collectionItemTypeName = CommonUtil.GetCollectionItemTypeName(collectionTypeName, false);
                // Highly unlikely, but the method return null if the typeName argument does not meet certain expectations
                if (collectionItemTypeName == null)
                {
                    return;
                }

                Type collectionItemType = ResolveClientTypeForDynamicProperty(collectionItemTypeName, entry.ResolvedObject);

                if (collectionItemType != null && ClientTypeUtil.TypeIsComplex(collectionItemType, model))
                {
                    Type  collectionType = typeof(System.Collections.ObjectModel.Collection <>).MakeGenericType(new Type[] { collectionItemType });
                    IList collection     = (IList)Util.ActivatorCreateInstance(collectionType);

                    IEnumerable <ODataResource> feedEntries = MaterializerFeed.GetFeed(linkState.Feed).Entries;
                    foreach (ODataResource feedEntry in feedEntries)
                    {
                        MaterializerEntry linkEntry = MaterializerEntry.GetEntry(feedEntry);
                        this.Materialize(linkEntry, collectionItemType, false /*includeLinks*/);
                        collection.Add(linkEntry.ResolvedObject);
                    }
                    containerProperty.Add(link.Name, collection);
                }
            }
            else
            {
                MaterializerEntry linkEntry = linkState.Entry;
                Type itemType = ResolveClientTypeForDynamicProperty(linkEntry.Entry.TypeName, entry.ResolvedObject);

                if (itemType != null && ClientTypeUtil.TypeIsComplex(itemType, model))
                {
                    this.Materialize(linkEntry, itemType, false /*includeLinks*/);
                    containerProperty.Add(link.Name, linkEntry.ResolvedObject);
                }
            }
        }
 /// <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>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>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>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));
 }