internal ClientTypeAnnotation(IEdmType edmType, Type type, string qualifiedName, ClientEdmModel model)
        {
            Debug.Assert(edmType != null, "edmType != null");
            Debug.Assert(null != type, "null type");
            Debug.Assert(!string.IsNullOrEmpty(qualifiedName), "!string.IsNullOrEmpty(qualifiedName)");

            this.EdmType = edmType;
            this.EdmTypeReference = this.EdmType.ToEdmTypeReference(Util.IsNullableType(type));
            this.ElementTypeName = qualifiedName;
            this.ElementType = Nullable.GetUnderlyingType(type) ?? type;
            this.model = model;
        }
Esempio n. 2
0
        public ClientEdmStructuredValueTests()
        {
            this._address = new Address {
                Street = "123 fake st"
            };
            this._entity = new Customer {
                Id = 1, Address = this._address, Emails = new List <string> {
                    "*****@*****.**"
                }
            };

            var model       = new ClientEdmModel(ODataProtocolVersion.V4);
            var entityType  = model.GetOrCreateEdmType(typeof(Customer));
            var complexType = model.GetOrCreateEdmType(typeof(Address));

            this._complexValue = new ClientEdmStructuredValue(this._address, model, model.GetClientTypeAnnotation(complexType));
            this._entityValue  = new ClientEdmStructuredValue(this._entity, model, model.GetClientTypeAnnotation(entityType));
        }
        public void DeclaringTypeOFAnEntityNavigationCanBeAComplexType()
        {
            //Arrange
            Type        complexDeclaringType      = typeof(Address);
            Type        entityNavigationType      = typeof(City);
            EdmTypeKind expectedDeclaringTypeKind = EdmTypeKind.Complex;

            //Act
            ClientEdmModel        clientEdmModel = new ClientEdmModel(ODataProtocolVersion.V401);
            IEdmType              edmTypeOfComplexDeclaringType = clientEdmModel.GetOrCreateEdmType(complexDeclaringType);
            IEdmType              edmTypeOfEntityNavigationType = clientEdmModel.GetOrCreateEdmType(entityNavigationType);
            IEdmStructuredType    entiyNavigationType           = clientEdmModel.GetOrCreateEdmType(complexDeclaringType) as IEdmStructuredType;
            EdmNavigationProperty edmNavigationProperty         = EdmNavigationProperty.CreateNavigationPropertyWithPartner("City", ClientTypeUtil.ToEdmTypeReference(edmTypeOfEntityNavigationType, true), null, null, false, EdmOnDeleteAction.None, "Partner", ClientTypeUtil.ToEdmTypeReference(edmTypeOfComplexDeclaringType, true), null, null, false, EdmOnDeleteAction.None);
            EdmTypeKind           resultingDeclaringTypeKind    = edmNavigationProperty.DeclaringType.TypeKind;

            //Assert
            Assert.Equal(expectedDeclaringTypeKind, resultingDeclaringTypeKind);
        }
Esempio n. 4
0
        /// <summary>
        /// Get or create a client EDM type instance.
        /// </summary>
        /// <param name="type">type to wrap</param>
        /// <returns>client type</returns>
        internal IEdmType GetOrCreateEdmType(Type type)
        {
            Debug.Assert(type != null, "type != null");

            EdmTypeCacheValue cachedEdmType;

            lock (this.clrToEdmTypeCache)
            {
                this.clrToEdmTypeCache.TryGetValue(type, out cachedEdmType);
            }

            if (cachedEdmType == null)
            {
                if (PrimitiveType.IsKnownNullableType(type))
                {
                    cachedEdmType = this.GetOrCreateEdmTypeInternal(null /*baseType*/, type, ClientTypeUtil.EmptyPropertyInfoArray, false /*isEntity*/, false /*hasProperties*/);
                }
                else
                {
                    PropertyInfo[] keyProperties;
                    bool           hasProperties;
                    Type[]         hierarchy = ClientEdmModel.GetTypeHierarchy(type, out keyProperties, out hasProperties);

                    Debug.Assert(keyProperties == null || keyProperties.Length == 0 || keyProperties.All(p => p.DeclaringType == keyProperties[0].DeclaringType), "All key properties must be declared on the same type.");

                    bool isEntity = keyProperties != null;
                    keyProperties = keyProperties ?? ClientTypeUtil.EmptyPropertyInfoArray;
                    foreach (Type t in hierarchy)
                    {
                        // Pass in the full list of key properties for the most base type to be added there.  We only allow key properties to be
                        // declared on the same type.
                        IEdmStructuredType edmBaseType = cachedEdmType == null ? null : cachedEdmType.EdmType as IEdmStructuredType;
                        cachedEdmType = this.GetOrCreateEdmTypeInternal(edmBaseType, t, keyProperties, isEntity, t == type ? hasProperties : (bool?)null);

                        // Pass in an empty PropertyInfo array on subsequent derived types.
                        keyProperties = ClientTypeUtil.EmptyPropertyInfoArray;
                    }
                }
            }

            Debug.Assert(cachedEdmType != null, "cachedEdmType != null");
            this.ValidateComplexType(type, cachedEdmType);
            return(cachedEdmType.EdmType);
        }
        /// <summary>
        /// Reads from message reader.
        /// </summary>
        /// <param name="expectedClientType">The expected client type being materialized into.</param>
        /// <param name="expectedReaderType">The expected type for the underlying reader.</param>
        protected override void ReadWithExpectedType(IEdmTypeReference expectedClientType, IEdmTypeReference expectedReaderType)
        {
            this.ReadLinks();

            Type underlyingExpectedType = Nullable.GetUnderlyingType(this.ExpectedType) ?? this.ExpectedType;

            ClientEdmModel       edmModel   = this.MaterializerContext.Model;
            ClientTypeAnnotation targetType = edmModel.GetClientTypeAnnotation(edmModel.GetOrCreateEdmType(underlyingExpectedType));

            // If the target type is an entity, then we should throw since the type on the wire was not an entity
            if (targetType.IsEntityType)
            {
                throw DSClient.Error.InvalidOperation(DSClient.Strings.AtomMaterializer_InvalidEntityType(targetType.ElementTypeName));
            }
            else
            {
                throw DSClient.Error.InvalidOperation(DSClient.Strings.Deserialize_MixedTextWithComment);
            }
        }
Esempio n. 6
0
        /// <summary>
        /// Checks if the provided type is a collection type (i.e. it implements ICollection and the collection item type is not an entity).
        /// </summary>
        /// <param name="type">Type being checked.</param>
        /// <param name="model">The client model.</param>
        /// <returns>True if the CLR type is a collection compatible type. False otherwise.</returns>
        internal static bool IsCLRTypeCollection(Type type, ClientEdmModel model)
        {
            // char[] and byte[] implements ICollection<> but we should not threat them as collections since they are primitive types for us.
            if (!PrimitiveType.IsKnownNullableType(type))
            {
                Type collectionType = ClientTypeUtil.GetImplementationType(type, typeof(ICollection <>));
                if (collectionType != null)
                {
                    // collectionType is ICollection so we know that the first generic parameter
                    // is the collection item type
                    if (!ClientTypeUtil.TypeIsEntity(collectionType.GetGenericArguments()[0], model))
                    {
                        return(true);
                    }
                }
            }

            return(false);
        }
Esempio n. 7
0
        internal EntryValueMaterializationPolicy CreateEntryMaterializationPolicy(TestMaterializerContext materializerContext = null)
        {
            var clientEdmModel = new ClientEdmModel(ODataProtocolVersion.V4);
            var context        = new DataServiceContext();

            materializerContext = materializerContext ?? new TestMaterializerContext()
            {
                Model = clientEdmModel, Context = context
            };
            var adapter = new EntityTrackingAdapter(new TestEntityTracker(), MergeOption.OverwriteChanges, clientEdmModel, context);
            var lazyPrimitivePropertyConverter   = new Microsoft.OData.Client.SimpleLazy <PrimitivePropertyConverter>(() => new PrimitivePropertyConverter());
            var primitiveValueMaterializerPolicy = new PrimitiveValueMaterializationPolicy(materializerContext, lazyPrimitivePropertyConverter);
            var entryPolicy             = new EntryValueMaterializationPolicy(materializerContext, adapter, lazyPrimitivePropertyConverter, null);
            var collectionPolicy        = new CollectionValueMaterializationPolicy(materializerContext, primitiveValueMaterializerPolicy);
            var intanceAnnotationPolicy = new InstanceAnnotationMaterializationPolicy(materializerContext);

            entryPolicy.CollectionValueMaterializationPolicy    = collectionPolicy;
            entryPolicy.InstanceAnnotationMaterializationPolicy = intanceAnnotationPolicy;

            return(entryPolicy);
        }
        private static ODataResource CreateODataEntry <T>(Action <EntityDescriptor> configureDescriptor = null, Action <DataServiceClientFormat> configureFormat = null, string serverTypeName = "serverTypeName", string clientTypeName = "clientTypeName")
        {
            ClientEdmModel model = new ClientEdmModel(ODataProtocolVersion.V4);
            var            ctx   = new DataServiceContext(new Uri("http://www.example.com/odata.svc"), ODataProtocolVersion.V4, model);

            EntityDescriptor entityDescriptor = new EntityDescriptor(model);

            if (configureDescriptor != null)
            {
                configureDescriptor(entityDescriptor);
            }

            if (configureFormat != null)
            {
                configureFormat(ctx.Format);
            }

            ClientTypeAnnotation clientTypeAnnotation = new ClientTypeAnnotation(new EdmEntityType("Fake", "Fake"), typeof(T), clientTypeName, model);

            return(Serializer.CreateODataEntry(entityDescriptor, serverTypeName, clientTypeAnnotation, ctx.Format));
        }
        public void ShortIntegrationTestToValidateEntryShouldBeRead()
        {
            var odataEntry = new ODataResource()
            {
                Id = new Uri("http://services.odata.org/OData/OData.svc/Customers(0)")
            };

            odataEntry.Properties = new ODataProperty[] { new ODataProperty()
                                                          {
                                                              Name = "ID", Value = 0
                                                          }, new ODataProperty()
                                                          {
                                                              Name = "Description", Value = "Simple Stuff"
                                                          } };

            var clientEdmModel = new ClientEdmModel(ODataProtocolVersion.V4);
            var context        = new DataServiceContext();

            MaterializerEntry.CreateEntry(odataEntry, ODataFormat.Json, true, clientEdmModel);
            var materializerContext = new TestMaterializerContext()
            {
                Model = clientEdmModel, Context = context
            };
            var             adapter    = new EntityTrackingAdapter(new TestEntityTracker(), MergeOption.OverwriteChanges, clientEdmModel, context);
            QueryComponents components = new QueryComponents(new Uri("http://foo.com/Service"), new Version(4, 0), typeof(Customer), null, new Dictionary <Expression, Expression>());

            var entriesMaterializer = new ODataEntriesEntityMaterializer(new ODataResource[] { odataEntry }, materializerContext, adapter, components, typeof(Customer), null, ODataFormat.Json);

            var customersRead = new List <Customer>();

            // This line will call ODataEntityMaterializer.ReadImplementation() which will reconstruct the entity, and will get non-public setter called.
            while (entriesMaterializer.Read())
            {
                customersRead.Add(entriesMaterializer.CurrentValue as Customer);
            }

            customersRead.Should().HaveCount(1);
            customersRead[0].ID.Should().Be(0);
            customersRead[0].Description.Should().Be("Simple Stuff");
        }
Esempio n. 10
0
        protected static void ApplyCollectionDataValues(ODataProperty collectionProperty, bool ignoreMissingProperties, System.Data.Services.Client.ResponseInfo responseInfo, object collectionInstance, Type collectionItemType, Action <object, object> AddValueToBackingICollectionInstance)
        {
            ODataCollectionValue value2 = collectionProperty.Value as ODataCollectionValue;

            if (value2.Items != null)
            {
                bool           flag  = PrimitiveType.IsKnownNullableType(collectionItemType);
                ClientEdmModel model = ClientEdmModel.GetModel(responseInfo.MaxProtocolVersion);
                foreach (object obj2 in value2.Items)
                {
                    if (obj2 == null)
                    {
                        throw System.Data.Services.Client.Error.InvalidOperation(System.Data.Services.Client.Strings.Collection_NullCollectionItemsNotSupported);
                    }
                    if (flag)
                    {
                        object obj3;
                        if ((obj2 is ODataComplexValue) || (obj2 is ODataCollectionValue))
                        {
                            throw System.Data.Services.Client.Error.InvalidOperation(System.Data.Services.Client.Strings.Collection_ComplexTypesInCollectionOfPrimitiveTypesNotAllowed);
                        }
                        MaterializePrimitiveDataValue(collectionItemType, value2.TypeName, obj2, responseInfo, () => System.Data.Services.Client.Strings.Collection_NullCollectionItemsNotSupported, out obj3);
                        AddValueToBackingICollectionInstance(collectionInstance, ConvertPrimitiveValue(obj2, collectionItemType));
                    }
                    else
                    {
                        ODataComplexValue value3 = obj2 as ODataComplexValue;
                        if (value3 == null)
                        {
                            throw System.Data.Services.Client.Error.InvalidOperation(System.Data.Services.Client.Strings.Collection_PrimitiveTypesInCollectionOfComplexTypesNotAllowed);
                        }
                        ClientTypeAnnotation clientTypeAnnotation = model.GetClientTypeAnnotation(model.GetOrCreateEdmType(collectionItemType));
                        object instance = clientTypeAnnotation.CreateInstance();
                        ApplyDataValues(clientTypeAnnotation, value3.Properties, ignoreMissingProperties, responseInfo, instance);
                        AddValueToBackingICollectionInstance(collectionInstance, instance);
                    }
                }
            }
            collectionProperty.SetMaterializedValue(collectionInstance);
        }
Esempio n. 11
0
 private bool TryResolveFromContext(MaterializerEntry entry, Type expectedEntryType)
 {
     if (this.mergeOption != MergeOption.NoTracking)
     {
         EntityStates states;
         entry.ResolvedObject = base.ResponseInfo.EntityTracker.TryGetEntity(entry.Id, out states);
         if (entry.ResolvedObject != null)
         {
             if (!expectedEntryType.IsInstanceOfType(entry.ResolvedObject))
             {
                 throw System.Data.Services.Client.Error.InvalidOperation(System.Data.Services.Client.Strings.Deserialize_Current(expectedEntryType, entry.ResolvedObject.GetType()));
             }
             ClientEdmModel model = ClientEdmModel.GetModel(base.ResponseInfo.MaxProtocolVersion);
             entry.ActualType              = model.GetClientTypeAnnotation(model.GetOrCreateEdmType(entry.ResolvedObject.GetType()));
             entry.EntityHasBeenResolved   = true;
             entry.ShouldUpdateFromPayload = ((this.mergeOption == MergeOption.OverwriteChanges) || ((this.mergeOption == MergeOption.PreserveChanges) && (states == EntityStates.Unchanged))) || ((this.mergeOption == MergeOption.PreserveChanges) && (states == EntityStates.Deleted));
             this.log.FoundExistingInstance(entry);
             return(true);
         }
     }
     return(false);
 }
Esempio n. 12
0
        protected static void MaterializeComplexTypeProperty(Type propertyType, ODataComplexValue complexValue, bool ignoreMissingProperties, System.Data.Services.Client.ResponseInfo responseInfo)
        {
            object instance = null;

            if ((complexValue != null) && !complexValue.HasMaterializedValue())
            {
                ClientTypeAnnotation actualType = null;
                if (WebUtil.IsWireTypeCollection(complexValue.TypeName))
                {
                    actualType = responseInfo.TypeResolver.ResolveEdmTypeName(propertyType, complexValue.TypeName);
                }
                else
                {
                    ClientEdmModel model = ClientEdmModel.GetModel(responseInfo.MaxProtocolVersion);
                    actualType = model.GetClientTypeAnnotation(model.GetOrCreateEdmType(propertyType));
                }
                instance = Util.ActivatorCreateInstance(propertyType, new object[0]);
                MaterializeDataValues(actualType, complexValue.Properties, ignoreMissingProperties);
                ApplyDataValues(actualType, complexValue.Properties, ignoreMissingProperties, responseInfo, instance);
                complexValue.SetMaterializedValue(instance);
            }
        }
Esempio n. 13
0
        private void InitializeEdmModel()
        {
            this.clientModel        = new ClientEdmModel(ODataProtocolVersion.V4);
            this.dataServiceContext = new DataServiceContext(new Uri(ServiceUri), ODataProtocolVersion.V4, this.clientModel);
            this.dataServiceContext.UndeclaredPropertyBehavior = UndeclaredPropertyBehavior.Support;
            this.dataServiceContext.ResolveType = (typeName) =>
            {
                return(this.dataServiceContext.DefaultResolveType(typeName, "NS.Models", "NS.Models"));
            };

            this.dataServiceContext.ResolveName = (clientType) =>
            {
                var originalNameAttribute = (OriginalNameAttribute)Enumerable.SingleOrDefault(Utility.GetCustomAttributes(clientType, typeof(OriginalNameAttribute), true));
                if (clientType.Namespace.Equals("NS.Models", global::System.StringComparison.Ordinal))
                {
                    if (originalNameAttribute != null)
                    {
                        return(string.Concat("NS.Models.", originalNameAttribute.OriginalName));
                    }

                    return(string.Concat("NS.Models.", clientType.Name));
                }

                if (originalNameAttribute != null)
                {
                    return(clientType.Namespace + "." + originalNameAttribute.OriginalName);
                }

                return(clientType.FullName);
            };

            using (var reader = XmlReader.Create(new StringReader(CamelCasedEdmx)))
            {
                if (CsdlReader.TryParse(reader, out IEdmModel serviceModel, out _))
                {
                    this.dataServiceContext.Format.UseJson(serviceModel);
                }
            }
        }
Esempio n. 14
0
        /// <summary>Materializes a complex type property.</summary>
        /// <param name="propertyType">Type of the complex type to set.</param>
        /// <param name="complexValue">The OData complex value.</param>
        internal void MaterializeComplexTypeProperty(Type propertyType, ODataComplexValue complexValue)
        {
            //// TODO: we decide whether the type is primitive or complex only based on the payload. If there is a mismatch we throw a random exception.
            //// We should have a similar check to the one we have for non-projection codepath here.
            if (complexValue == null || complexValue.HasMaterializedValue())
            {
                return;
            }

            ClientTypeAnnotation complexType = null;

            // TODO: We should call type resolver for complex types for projections if they are not instantiated by the user directly
            // with "new" operator. At the moment we don't do it at all. Let's be consistent for Collections and call type
            // resolver as we do in DirectMaterializationPlan (even though this is only for negative cases for Collections as property.IsCollection
            // must have been false otherwise we would have not end up here).
            // This bug is about investigating when we actually do call type resolver and fix it so that we call it when needed and don't
            // call it when we should not (i.e. it should not be called for types created with "new" operator").
            if (!string.IsNullOrEmpty(complexValue.TypeName))
            {
                complexType = this.MaterializerContext.ResolveTypeForMaterialization(propertyType, complexValue.TypeName);
            }
            else
            {
                ClientEdmModel edmModel = this.MaterializerContext.Model;
                complexType = edmModel.GetClientTypeAnnotation(edmModel.GetOrCreateEdmType(propertyType));
            }

            object complexInstance = this.CreateNewInstance(complexType.EdmType.ToEdmTypeReference(true), complexType.ElementType);

            this.MaterializeDataValues(complexType, complexValue.Properties, this.MaterializerContext.IgnoreMissingProperties);
            this.ApplyDataValues(complexType, complexValue.Properties, complexInstance);
            complexValue.SetMaterializedValue(complexInstance);

            if (!this.MaterializerContext.Context.DisableInstanceAnnotationMaterialization)
            {
                this.InstanceAnnotationMaterializationPolicy.SetInstanceAnnotations(complexValue, complexInstance);
            }
        }
Esempio n. 15
0
        public TypeResolverTests()
        {
            this.serverModel      = new EdmModel();
            this.clientModel      = new ClientEdmModel(ODataProtocolVersion.V4);
            this.clientEntityType = (IEdmEntityType)this.clientModel.GetOrCreateEdmType(typeof(TestClientEntityType));
            this.clientIdProperty = new EdmStructuralProperty(this.clientEntityType, "Id", EdmCoreModel.Instance.GetInt32(false));

            var serverType = new EdmEntityType("FQ.NS", "TestServerType");

            this.serverModel.AddElement(serverType);
            var serverContainer = new EdmEntityContainer("FQ.NS", "Container");

            this.serverModel.AddElement(serverContainer);
            serverContainer.AddEntitySet("Entities", serverType);

            var serverType2 = new EdmEntityType("FQ.NS", "TestServerType2");

            this.serverModel.AddElement(serverType2);
            serverType.AddUnidirectionalNavigation(new EdmNavigationPropertyInfo()
            {
                Name = "Navigation", Target = serverType2, TargetMultiplicity = EdmMultiplicity.ZeroOrOne
            });
        }
Esempio n. 16
0
        private void AssertPrimitiveTypeReferenceGeneration(bool makeNullable, string errorMessage)
        {
            foreach (var dataServiceProtocolVersion in new[] { ODataProtocolVersion.V4 })
            {
                ClientEdmModel clientEdmModel = new ClientEdmModel(dataServiceProtocolVersion);
                foreach (var primitivePropertyType in clrTypeToEdmTypeMapping)
                {
                    Type nullableType = primitivePropertyType.Value;
                    if (makeNullable)
                    {
                        nullableType = typeof(Nullable <>).MakeGenericType(primitivePropertyType.Value);
                    }

                    var primitiveEdmType = clientEdmModel.GetOrCreateEdmType(nullableType) as IEdmPrimitiveType;
                    Assert.Equal("Edm", primitiveEdmType.Namespace);
                    Assert.Equal(GetFullName(primitiveEdmType), primitivePropertyType.Key);
                    Assert.Equal(EdmTypeKind.Primitive, primitiveEdmType.TypeKind);

                    IEdmTypeReference primitiveTypeReference = primitiveEdmType.ToEdmTypeReference(makeNullable);
                    Assert.Equal(primitiveTypeReference.IsNullable, makeNullable);
                }
            }
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="ClientEdmStructuredValue"/> class.
        /// </summary>
        /// <param name="structuredValue">The structured value.</param>
        /// <param name="model">The model.</param>
        /// <param name="clientTypeAnnotation">The client type annotation.</param>
        public ClientEdmStructuredValue(object structuredValue, ClientEdmModel model, ClientTypeAnnotation clientTypeAnnotation)
        {
            Debug.Assert(structuredValue != null, "entity != null");
            Debug.Assert(model != null, "model != null");
            Debug.Assert(clientTypeAnnotation != null, "clientTypeAnnotation != null");

            if (clientTypeAnnotation.EdmType.TypeKind == EdmTypeKind.Complex)
            {
                // TODO: nullable?
                this.Type = new EdmComplexTypeReference((IEdmComplexType)clientTypeAnnotation.EdmType, true);
            }
            else
            {
                Debug.Assert(clientTypeAnnotation.EdmType.TypeKind == EdmTypeKind.Entity, "Only complex and entity values supported");

                // TODO: nullable?
                this.Type = new EdmEntityTypeReference((IEdmEntityType)clientTypeAnnotation.EdmType, true);
            }

            this.structuredValue = structuredValue;
            this.typeAnnotation  = clientTypeAnnotation;
            this.model           = model;
        }
Esempio n. 18
0
        /// <summary>
        /// Get the entity set name for the target entity object.
        /// </summary>
        /// <param name="target">An entity object.</param>
        /// <param name="targetEntitySet">The 'currently known' entity set name for the target object.</param>
        /// <param name="model">The client model.</param>
        /// <returns>The entity set name for the target object.</returns>
        /// <remarks>
        /// Allow user code to provide the entity set name. If user code does not provide the entity set name, then
        /// this method will get the entity set name from the value of the EntitySetAttribute.
        /// The 'currently known' entity set name for top level collections can be provided through OEC constructor
        /// </remarks>
        internal static string GetEntitySet(
            object target,
            string targetEntitySet,
            ClientEdmModel model)
        {
            Debug.Assert(target != null, "Argument 'target' cannot be null.");
            Debug.Assert(BindingEntityInfo.IsEntityType(target.GetType(), model), "Argument 'target' must be an entity type.");

            // Here's the rules in order of priority for resolving entity set name
            // 1. EntitySet name passed in the constructor or extension methods of DataServiceCollection
            // 2. EntitySet name specified in the EntitySet attribute by the code gen. {Remember this attribute is
            //    not generated in case of MEST)
            if (!String.IsNullOrEmpty(targetEntitySet))
            {
                return(targetEntitySet);
            }
            else
            {
                // If there is not a 'currently known' entity set name to validate against, then there must be
                // EntitySet attribute on the entity type
                return(BindingEntityInfo.GetEntitySetAttribute(target.GetType(), model));
            }
        }
Esempio n. 19
0
        private void ApplyInnerProperty(ODataResource innerResource, ComplexTypeWithChildComplexType parentInstance, TestMaterializerContext context = null)
        {
            context = context ?? new TestMaterializerContext();
            var resource = new ODataResource()
            {
                TypeName = "ComplexTypeWithChildComplexType", Properties = new ODataProperty[0]
            };

            var clientEdmModel    = new ClientEdmModel(ODataProtocolVersion.V4);
            var materializerEntry = MaterializerEntry.CreateEntry(resource, ODataFormat.Json, false, clientEdmModel);

            materializerEntry.ResolvedObject = parentInstance;
            ODataNestedResourceInfo innerComplexP = new ODataNestedResourceInfo()
            {
                Name = "InnerComplexProperty", IsCollection = false
            };

            MaterializerEntry innerMaterializerEntry;

            if (innerResource != null)
            {
                innerMaterializerEntry = MaterializerEntry.CreateEntry(innerResource, ODataFormat.Json, true, clientEdmModel);
            }
            else
            {
                innerMaterializerEntry = MaterializerEntry.CreateEmpty();
            }

            MaterializerNavigationLink.CreateLink(innerComplexP, innerMaterializerEntry);
            materializerEntry.AddNestedResourceInfo(innerComplexP);

            var policy = this.CreateEntryMaterializationPolicy(context);

            policy.EntityTrackingAdapter.TargetInstance = parentInstance;
            policy.Materialize(materializerEntry, typeof(ComplexTypeWithChildComplexType), true);
        }
Esempio n. 20
0
        /// <summary>Tries to resolve the object as the target one in a POST refresh.</summary>
        /// <param name="entry">Entry to resolve.</param>
        /// <returns>true if the entity was resolved; false otherwise.</returns>
        private bool TryResolveAsTarget(MaterializerEntry entry)
        {
            if (entry.ResolvedObject == null)
            {
                return(false);
            }

            // The only case when the entity hasn't been resolved but
            // it has already been set is when the target instance
            // was set directly to refresh a POST.
            Debug.Assert(
                entry.ResolvedObject == this.TargetInstance,
                "entry.ResolvedObject == this.TargetInstance -- otherwise there we ResolveOrCreateInstance more than once on the same entry");
            Debug.Assert(
                this.MergeOption == MergeOption.OverwriteChanges || this.MergeOption == MergeOption.PreserveChanges,
                "MergeOption.OverwriteChanges and MergeOption.PreserveChanges are the only expected values during SaveChanges");
            ClientEdmModel edmModel = this.Model;

            entry.ActualType = edmModel.GetClientTypeAnnotation(edmModel.GetOrCreateEdmType(entry.ResolvedObject.GetType()));
            this.MaterializationLog.FoundTargetInstance(entry);
            entry.ShouldUpdateFromPayload = this.MergeOption != MergeOption.PreserveChanges;
            entry.EntityHasBeenResolved   = true;
            return(true);
        }
Esempio n. 21
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);
                }
            }
        }
Esempio n. 22
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()));
                }
            }
        }
Esempio n. 23
0
        /// <summary>
        /// Validates the specified <paramref name="property"/> matches
        /// the parsed <paramref name="link"/>.
        /// </summary>
        /// <param name="property">Property as understood by the type system.</param>
        /// <param name="link">Property as parsed.</param>
        /// <param name="model">Client Model.</param>
        /// <param name="performEntityCheck">whether to do the entity check or not.</param>
        /// <returns>The type</returns>
        internal static Type ValidatePropertyMatch(ClientPropertyAnnotation property, ODataNestedResourceInfo link, ClientEdmModel model, bool performEntityCheck)
        {
            Debug.Assert(property != null, "property != null");
            Debug.Assert(link != null, "link != null");

            Type propertyType = null;

            if (link.IsCollection.HasValue)
            {
                if (link.IsCollection.Value)
                {
                    // We need to fail if the payload states that the property is a navigation collection property or a complex collection property
                    // and in the client, the property is not a collection property.
                    if (!property.IsResourceSet)
                    {
                        throw DSClient.Error.InvalidOperation(DSClient.Strings.Deserialize_MismatchAtomLinkFeedPropertyNotCollection(property.PropertyName));
                    }

                    propertyType = property.ResourceSetItemType;
                }
                else
                {
                    if (property.IsResourceSet)
                    {
                        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.TypeIsStructured(propertyType, model))
                {
                    throw DSClient.Error.InvalidOperation(DSClient.Strings.AtomMaterializer_InvalidNonEntityType(propertyType.ToString()));
                }
            }

            return(propertyType);
        }
Esempio n. 24
0
        /// <summary>
        /// Creates a new instance of MaterializerEntry.
        /// </summary>
        /// <param name="entry">The entry.</param>
        /// <param name="format">The format the entry was read in.</param>
        /// <param name="isTracking">True if the contents of the entry will be tracked in the context, otherwise False.</param>
        /// <param name="model">The client model.</param>
        private MaterializerEntry(ODataEntry entry, ODataFormat format, bool isTracking, ClientEdmModel model)
        {
            Debug.Assert(entry != null, "entry != null");

            this.entry            = entry;
            this.Format           = format;
            this.entityDescriptor = new EntityDescriptor(model);
#pragma warning disable 618
            this.isAtomOrTracking = isTracking || this.Format == ODataFormat.Atom;
#pragma warning restore 618
            string serverTypeName = this.Entry.TypeName;
            SerializationTypeNameAnnotation serializationTypeNameAnnotation = entry.GetAnnotation <SerializationTypeNameAnnotation>();
            if (serializationTypeNameAnnotation != null)
            {
                // If the annotation has a value use it. Otherwise, in JSON-Light, the types can be inferred from the
                // context URI even if they are not present on the wire, so just use the type name from the entry.
                if (serializationTypeNameAnnotation.TypeName != null || this.Format != ODataFormat.Json)
                {
                    serverTypeName = serializationTypeNameAnnotation.TypeName;
                }
            }

            this.entityDescriptor.ServerTypeName = serverTypeName;
        }
Esempio n. 25
0
        /// <summary>
        /// Creates the materializer entry.
        /// </summary>
        /// <param name="entry">The entry.</param>
        /// <param name="format">The format the entry was read in.</param>
        /// <param name="isTracking">True if the contents of the entry will be tracked in the context, otherwise False.</param>
        /// <param name="model">The client model.</param>
        /// <returns>A new materializer entry.</returns>
        public static MaterializerEntry CreateEntry(ODataEntry entry, ODataFormat format, bool isTracking, ClientEdmModel model)
        {
            Debug.Assert(entry.GetAnnotation <MaterializerEntry>() == null, "MaterializerEntry has already been created.");

            MaterializerEntry materializerEntry = new MaterializerEntry(entry, format, isTracking, model);

            entry.SetAnnotation <MaterializerEntry>(materializerEntry);

            return(materializerEntry);
        }
 public TestClientContext(Uri serviceRoot, ODataProtocolVersion version, ClientEdmModel model)
     : base(serviceRoot, version, model)
 {
 }
Esempio n. 27
0
        /// <summary>
        /// Is the type an structured type?
        /// </summary>
        /// <param name="t">Type to examine</param>
        /// <param name="model">The client model.</param>
        /// <returns>bool indicating whether or not structured type</returns>
        internal static bool TypeIsStructured(Type t, ClientEdmModel model)
        {
            var typeKind = model.GetOrCreateEdmType(t).TypeKind;

            return(typeKind == EdmTypeKind.Entity || typeKind == EdmTypeKind.Complex);
        }
Esempio n. 28
0
 /// <summary>
 /// Is the type a Complex Type?
 /// </summary>
 /// <param name="t">Type to examine</param>
 /// <param name="model">The client model.</param>
 /// <returns>bool indicating whether or not complex type</returns>
 internal static bool TypeIsComplex(Type t, ClientEdmModel model)
 {
     return(model.GetOrCreateEdmType(t).TypeKind == EdmTypeKind.Complex);
 }
Esempio n. 29
0
 /// <summary>
 /// Is the type an Entity Type?
 /// </summary>
 /// <param name="t">Type to examine</param>
 /// <param name="model">The client model.</param>
 /// <returns>bool indicating whether or not entity type</returns>
 internal static bool TypeIsEntity(Type t, ClientEdmModel model)
 {
     return(model.GetOrCreateEdmType(t).TypeKind == EdmTypeKind.Entity);
 }
Esempio n. 30
0
 /// <summary>
 /// Initializes a new instance of the <see cref="EntityTrackingAdapter" /> class.
 /// </summary>
 /// <param name="entityTracker">The entity tracker.</param>
 /// <param name="mergeOption">The merge option.</param>
 /// <param name="model">The model.</param>
 /// <param name="context">The context.</param>
 internal EntityTrackingAdapter(EntityTrackerBase entityTracker, MergeOption mergeOption, ClientEdmModel model, DataServiceContext context)
 {
     this.MaterializationLog = new AtomMaterializerLog(mergeOption, model, entityTracker);
     this.MergeOption        = mergeOption;
     this.EntityTracker      = entityTracker;
     this.Model   = model;
     this.Context = context;
 }
Esempio n. 31
0
 /// <summary>
 /// gets the UriTranslateResult for a the query
 /// </summary>
 /// <param name="model">The client model.</param>
 /// <returns>an instance of QueryComponents.</returns>
 internal override QueryComponents QueryComponents(ClientEdmModel model)
 {
     return(this.Translate());
 }