diff --git a/src/Microsoft.AspNet.OData.Shared/Query/Expressions/SelectExpandBinder.cs b/src/Microsoft.AspNet.OData.Shared/Query/Expressions/SelectExpandBinder.cs index 1e83b186e5..9d3cb65228 100644 --- a/src/Microsoft.AspNet.OData.Shared/Query/Expressions/SelectExpandBinder.cs +++ b/src/Microsoft.AspNet.OData.Shared/Query/Expressions/SelectExpandBinder.cs @@ -346,10 +346,16 @@ internal Expression ProjectElement(Expression source, SelectExpandClause selectE } } } + if (isInstancePropertySet) + { + Type wrapperGenericType = GetWrapperGenericType(isInstancePropertySet, isTypeNamePropertySet, isContainerPropertySet); + wrapperType = wrapperGenericType.MakeGenericType(elementType); + return Expression.MemberInit(Expression.New(wrapperType), wrapperTypeMemberAssignments); + } + ConstructorInfo constructorWithInstanse = wrapperType.GetConstructors().Single(c => c.GetParameters().Length == 1); + return Expression.MemberInit(Expression.New(constructorWithInstanse, source), wrapperTypeMemberAssignments); + - Type wrapperGenericType = GetWrapperGenericType(isInstancePropertySet, isTypeNamePropertySet, isContainerPropertySet); - wrapperType = wrapperGenericType.MakeGenericType(elementType); - return Expression.MemberInit(Expression.New(wrapperType), wrapperTypeMemberAssignments); } /// diff --git a/src/Microsoft.AspNet.OData.Shared/Query/Expressions/SelectExpandWrapperOfT.cs b/src/Microsoft.AspNet.OData.Shared/Query/Expressions/SelectExpandWrapperOfT.cs index d06afd4d55..9fa9714797 100644 --- a/src/Microsoft.AspNet.OData.Shared/Query/Expressions/SelectExpandWrapperOfT.cs +++ b/src/Microsoft.AspNet.OData.Shared/Query/Expressions/SelectExpandWrapperOfT.cs @@ -17,6 +17,16 @@ namespace Microsoft.AspNet.OData.Query.Expressions [JsonConverter(typeof(SelectExpandWrapperConverter))] internal class SelectExpandWrapper : SelectExpandWrapper { + public SelectExpandWrapper(TElement element) + { + Instance = element; + } + + public SelectExpandWrapper() + { + + } + /// /// Gets or sets the instance of the element being selected and expanded. /// diff --git a/test/UnitTest/Microsoft.AspNet.OData.Test.Shared/Query/Expressions/SelectExpandBinderTest.cs b/test/UnitTest/Microsoft.AspNet.OData.Test.Shared/Query/Expressions/SelectExpandBinderTest.cs index b360b48ed5..0f94e1b7c9 100644 --- a/test/UnitTest/Microsoft.AspNet.OData.Test.Shared/Query/Expressions/SelectExpandBinderTest.cs +++ b/test/UnitTest/Microsoft.AspNet.OData.Test.Shared/Query/Expressions/SelectExpandBinderTest.cs @@ -109,10 +109,12 @@ public void Bind_GeneratedExpression_ContainsExpandedObject() // Assert IEnumerator enumerator = queryable.GetEnumerator(); + IEnumerator _querableEnumerator = _queryable.GetEnumerator(); Assert.True(enumerator.MoveNext()); + Assert.True(_querableEnumerator.MoveNext()); var partialCustomer = Assert.IsAssignableFrom>(enumerator.Current); Assert.False(enumerator.MoveNext()); - Assert.Null(partialCustomer.Instance); + Assert.Equal(_querableEnumerator.Current, partialCustomer.Instance); Assert.Equal("Microsoft.AspNet.OData.Test.Query.Expressions.QueryCustomer", partialCustomer.InstanceType); IEnumerable> innerOrders = partialCustomer.Container .ToDictionary(PropertyMapper)["Orders"] as IEnumerable>; @@ -464,7 +466,7 @@ public void ProjectAsWrapper_Element_ProjectedValueContainsInstance_IfSelectionI } [Fact] - public void ProjectAsWrapper_Element_ProjectedValueDoesNotContainInstance_IfSelectionIsPartial() + public void ProjectAsWrapper_Element_ProjectedValueShouldContainInstance_IfSelectionIsPartial() { // Arrange string select = "Id,Orders"; @@ -486,7 +488,7 @@ public void ProjectAsWrapper_Element_ProjectedValueDoesNotContainInstance_IfSele Assert.Empty((projection as MemberInitExpression).Bindings.Where(p => p.Member.Name == "Instance")); Assert.NotEmpty((projection as MemberInitExpression).Bindings.Where(p => p.Member.Name == "InstanceType")); SelectExpandWrapper customerWrapper = Expression.Lambda(projection).Compile().DynamicInvoke() as SelectExpandWrapper; - Assert.Null(customerWrapper.Instance); + Assert.Equal(aCustomer, customerWrapper.Instance); Assert.Equal("Microsoft.AspNet.OData.Test.Query.Expressions.QueryCustomer", customerWrapper.InstanceType); } diff --git a/test/UnitTest/Microsoft.AspNet.OData.Test.Shared/Query/Expressions/SelectExpandWrapperTest.cs b/test/UnitTest/Microsoft.AspNet.OData.Test.Shared/Query/Expressions/SelectExpandWrapperTest.cs index c2ff968ce6..0892162fac 100644 --- a/test/UnitTest/Microsoft.AspNet.OData.Test.Shared/Query/Expressions/SelectExpandWrapperTest.cs +++ b/test/UnitTest/Microsoft.AspNet.OData.Test.Shared/Query/Expressions/SelectExpandWrapperTest.cs @@ -76,10 +76,10 @@ public void TryGetValue_ReturnsValueFromPropertyContainer_IfPresent() MockPropertyContainer container = new MockPropertyContainer(); container.Properties.Add("SampleProperty", expectedPropertyValue); SelectExpandWrapper wrapper = new SelectExpandWrapper - { - ModelID = _modelID, - Container = container - }; + { + ModelID = _modelID, + Container = container + }; wrapper.Instance = new TestEntity(); object value; @@ -95,10 +95,10 @@ public void TryGetValue_ReturnsValueFromInstance_IfNotPresentInContainer() object expectedPropertyValue = new object(); MockPropertyContainer container = new MockPropertyContainer(); SelectExpandWrapper wrapper = new SelectExpandWrapper - { - ModelID = _modelID, - Container = container - }; + { + ModelID = _modelID, + Container = container + }; wrapper.Instance = new TestEntity { SampleProperty = expectedPropertyValue }; wrapper.UseInstanceForProperties = true; @@ -133,7 +133,7 @@ public void TryGetValue_PropertyAliased_IfAnnotationSet() _model.CustomerName, new ClrPropertyInfoAnnotation(typeof(TestEntityWithAlias).GetProperty("SampleProperty"))); object expectedPropertyValue = new object(); - SelectExpandWrapper wrapper = new SelectExpandWrapper { ModelID = _modelID }; + SelectExpandWrapper wrapper = new SelectExpandWrapper() { ModelID = _modelID }; wrapper.Instance = new TestEntityWithAlias { SampleProperty = expectedPropertyValue }; wrapper.UseInstanceForProperties = true; @@ -248,7 +248,7 @@ public void ToDictionary_Throws_IfMapperProvider_ReturnsNullPropertyMapper() (IEdmModel m, IEdmStructuredType t) => null; // Act & Assert - ExceptionAssert.Throws(() => + ExceptionAssert.Throws(() => wrapper.ToDictionary(mapperProvider: mapperProvider), "The mapper provider must return a valid 'Microsoft.AspNet.OData.Query.IPropertyMapper' instance for the given 'NS.Name' IEdmType."); } @@ -261,12 +261,12 @@ public void ToDictionary_Throws_IfMappingIsNullOrEmpty_ForAGivenProperty(string // Arrange EdmEntityType entityType = new EdmEntityType("NS", "Name"); entityType.AddStructuralProperty("SampleProperty", EdmPrimitiveTypeKind.Int32); - + EdmModel model = new EdmModel(); model.AddElement(entityType); model.SetAnnotationValue(entityType, new ClrTypeAnnotation(typeof(TestEntity))); IEdmTypeReference edmType = new EdmEntityTypeReference(entityType, isNullable: false); - + SelectExpandWrapper testWrapper = new SelectExpandWrapper { Instance = new TestEntity { SampleProperty = 42 }, @@ -281,7 +281,7 @@ public void ToDictionary_Throws_IfMappingIsNullOrEmpty_ForAGivenProperty(string // Act & Assert ExceptionAssert.Throws(() => - testWrapper.ToDictionary(mapperProvider), + testWrapper.ToDictionary(mapperProvider), "The key mapping for the property 'SampleProperty' can't be null or empty."); } @@ -291,19 +291,19 @@ public void ToDictionary_AppliesMappingToAllProperties_IfInstanceIsNotNull() // Arrange EdmEntityType entityType = new EdmEntityType("NS", "Name"); entityType.AddStructuralProperty("SampleProperty", EdmPrimitiveTypeKind.Int32); - + EdmModel model = new EdmModel(); model.AddElement(entityType); model.SetAnnotationValue(entityType, new ClrTypeAnnotation(typeof(TestEntity))); IEdmTypeReference edmType = new EdmEntityTypeReference(entityType, isNullable: false); - + SelectExpandWrapper testWrapper = new SelectExpandWrapper { Instance = new TestEntity { SampleProperty = 42 }, ModelID = ModelContainer.GetModelID(model), UseInstanceForProperties = true, }; - + Mock mapperMock = new Mock(); mapperMock.Setup(m => m.MapProperty("SampleProperty")).Returns("Sample"); Func mapperProvider =