Skip to content

Commit 1f48bed

Browse files
authored
Add Instance annotations to WebAPI (#2219)
* InstanceAnnotationChanges InstanceAnnotationChanges * Update ODataResourceDeserializerTests.cs * Add review comments * Review comment fix * Code review changes Code review changes * updates * Update ODataResourceSerializer.cs * changes after rebase * InstanceAnnotationChanges InstanceAnnotationChanges * Add review comments * Review comment fix * Code review changes Code review changes * Update Microsoft.AspNet.OData.PublicApi.bsl * public api * public api change * Address comments * Changes * Update ODataResourceSerializer.cs * changes * Comment changes * Update ODataResourceSerializer.cs * publi api * comment chantes * extra test * Update GlobalSuppressions.cs * name change * changes * changes and test * Update ODataResourceValueSerializer.cs * changes * Update ODataResourceValueSerializer.cs * changes * changes * updates * Update ODataInstanceAnnotationContainer.cs
1 parent e812738 commit 1f48bed

File tree

43 files changed

+3482
-166
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+3482
-166
lines changed

src/Microsoft.AspNet.OData.Shared/Builder/EdmModelHelperMethods.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -460,6 +460,9 @@ private static Dictionary<Type, IEdmType> AddTypes(this EdmModel model, EdmTypeM
460460
// add dynamic dictionary property annotation for open types
461461
model.AddDynamicPropertyDictionaryAnnotations(edmTypeMap.OpenTypes);
462462

463+
// add instance annotation dictionary property annotations
464+
model.AddInstanceAnnotationsContainer(edmTypeMap.InstanceAnnotatableTypes);
465+
463466
return edmTypes;
464467
}
465468

@@ -554,6 +557,16 @@ private static void AddDynamicPropertyDictionaryAnnotations(this EdmModel model,
554557
}
555558
}
556559

560+
private static void AddInstanceAnnotationsContainer(this EdmModel model,
561+
Dictionary<IEdmStructuredType, PropertyInfo> instanceAnnotations)
562+
{
563+
foreach (KeyValuePair<IEdmStructuredType, PropertyInfo> instanceAnnotation in instanceAnnotations)
564+
{
565+
IEdmStructuredType edmStructuredType = instanceAnnotation.Key;
566+
PropertyInfo propertyInfo = instanceAnnotation.Value;
567+
model.SetAnnotationValue(edmStructuredType, new ODataInstanceAnnotationContainerAnnotation(propertyInfo));
568+
}
569+
}
557570
private static void AddPropertiesQuerySettings(this EdmModel model,
558571
Dictionary<IEdmProperty, ModelBoundQuerySettings> edmPropertiesQuerySettings)
559572
{

src/Microsoft.AspNet.OData.Shared/Builder/EdmTypeBuilder.cs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ internal class EdmTypeBuilder
3030
private readonly Dictionary<IEdmStructuredType, ModelBoundQuerySettings> _structuredTypeQuerySettings = new Dictionary<IEdmStructuredType, ModelBoundQuerySettings>();
3131
private readonly Dictionary<Enum, IEdmEnumMember> _members = new Dictionary<Enum, IEdmEnumMember>();
3232
private readonly Dictionary<IEdmStructuredType, PropertyInfo> _openTypes = new Dictionary<IEdmStructuredType, PropertyInfo>();
33+
private readonly Dictionary<IEdmStructuredType, PropertyInfo> _instanceAnnotableTypes = new Dictionary<IEdmStructuredType, PropertyInfo>();
3334

3435
internal EdmTypeBuilder(IEnumerable<IEdmTypeConfiguration> configurations)
3536
{
@@ -44,6 +45,7 @@ private Dictionary<Type, IEdmType> GetEdmTypes()
4445
_members.Clear();
4546
_openTypes.Clear();
4647
_propertyConfigurations.Clear();
48+
_instanceAnnotableTypes.Clear();
4749

4850
// Create headers to allow CreateEdmTypeBody to blindly references other things.
4951
foreach (IEdmTypeConfiguration config in _configurations)
@@ -91,6 +93,13 @@ private void CreateEdmTypeHeader(IEdmTypeConfiguration config)
9193
// add a mapping between the open complex type and its dynamic property dictionary.
9294
_openTypes.Add(complexType, complex.DynamicPropertyDictionary);
9395
}
96+
97+
if (complex.SupportsInstanceAnnotations)
98+
{
99+
// add a mapping between the complex type and its instance annotation dictionary.
100+
_instanceAnnotableTypes.Add(complexType, complex.InstanceAnnotationsContainer);
101+
}
102+
94103
edmType = complexType;
95104
}
96105
else if (config.Kind == EdmTypeKind.Entity)
@@ -116,6 +125,13 @@ private void CreateEdmTypeHeader(IEdmTypeConfiguration config)
116125
// add a mapping between the open entity type and its dynamic property dictionary.
117126
_openTypes.Add(entityType, entity.DynamicPropertyDictionary);
118127
}
128+
129+
if (entity.SupportsInstanceAnnotations)
130+
{
131+
// add a mapping between the entity type and its instance annotation dictionary.
132+
_instanceAnnotableTypes.Add(entityType, entity.InstanceAnnotationsContainer);
133+
}
134+
119135
edmType = entityType;
120136
}
121137
else
@@ -551,7 +567,8 @@ public static EdmTypeMap GetTypesAndProperties(IEnumerable<IEdmTypeConfiguration
551567
builder._structuredTypeQuerySettings,
552568
builder._members,
553569
builder._openTypes,
554-
builder._propertyConfigurations);
570+
builder._propertyConfigurations,
571+
builder._instanceAnnotableTypes);
555572
}
556573

557574
/// <summary>

src/Microsoft.AspNet.OData.Shared/Builder/EdmTypeMap.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ public EdmTypeMap(
1919
Dictionary<IEdmStructuredType, ModelBoundQuerySettings> edmStructuredTypeQuerySettings,
2020
Dictionary<Enum, IEdmEnumMember> enumMembers,
2121
Dictionary<IEdmStructuredType, PropertyInfo> openTypes,
22-
Dictionary<IEdmProperty, PropertyConfiguration> propertyConfigurations)
22+
Dictionary<IEdmProperty, PropertyConfiguration> propertyConfigurations,
23+
Dictionary<IEdmStructuredType, PropertyInfo> instanceAnnotatableTypes )
2324
{
2425
EdmTypes = edmTypes;
2526
EdmProperties = edmProperties;
@@ -29,6 +30,7 @@ public EdmTypeMap(
2930
EnumMembers = enumMembers;
3031
OpenTypes = openTypes;
3132
EdmPropertyConfigurations = propertyConfigurations;
33+
InstanceAnnotatableTypes = instanceAnnotatableTypes;
3234
}
3335

3436
public Dictionary<Type, IEdmType> EdmTypes { get; private set; }
@@ -46,5 +48,7 @@ public EdmTypeMap(
4648
public Dictionary<Enum, IEdmEnumMember> EnumMembers { get; private set; }
4749

4850
public Dictionary<IEdmStructuredType, PropertyInfo> OpenTypes { get; private set; }
51+
52+
public Dictionary<IEdmStructuredType, PropertyInfo> InstanceAnnotatableTypes { get; private set; }
4953
}
5054
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License. See License.txt in the project root for license information.
3+
4+
using System;
5+
using System.Collections.Generic;
6+
using System.Text;
7+
8+
namespace Microsoft.AspNet.OData.Builder
9+
{
10+
/// <summary>
11+
/// Interface to used as a Container for holding Instance Annotations, An default implementation is provided
12+
/// Custoer can implement the interface and can have their own implementation.
13+
/// </summary>
14+
public interface IODataInstanceAnnotationContainer
15+
{
16+
/// <summary>
17+
/// Method to Add an Instance Annotation to the CLR type
18+
/// </summary>
19+
/// <param name="annotationName">Name of Annotation</param>
20+
/// <param name="value">Value of Annotation</param>
21+
void AddResourceAnnotation(string annotationName, object value);
22+
23+
/// <summary>
24+
/// Method to Add an Instance Annotation to a property
25+
/// </summary>
26+
/// <param name="propertyName">Name of the property</param>
27+
/// <param name="annotationName">Name of Annotation</param>
28+
/// <param name="value">Value of Annotation</param>
29+
void AddPropertyAnnotation(string propertyName, string annotationName, object value);
30+
31+
/// <summary>
32+
/// Get an Instance Annotation from CLR Type
33+
/// </summary>
34+
/// <param name="annotationName">Name of Annotation</param>
35+
/// <returns>Get Annotation value for the given annotation</returns>
36+
object GetResourceAnnotation(string annotationName);
37+
38+
/// <summary>
39+
/// Get an Instance Annotation from the Property
40+
/// </summary>
41+
/// <param name="propertyName">Name of the Property</param>
42+
/// <param name="annotationName">Name of the Annotation</param>
43+
/// <returns>Get Annotation value for the given annotation and property</returns>
44+
object GetPropertyAnnotation(string propertyName, string annotationName);
45+
46+
/// <summary>
47+
/// Get All Annotations from CLR Type
48+
/// </summary>
49+
/// <returns>Dictionary of string(annotation name) and object value(annotation value)</returns>
50+
IDictionary<string,object> GetResourceAnnotations();
51+
52+
/// <summary>
53+
/// Get all Annotations for a Property
54+
/// </summary>
55+
/// <param name="propertyName">Name of Property</param>
56+
/// <returns>Dictionary of string(annotation name) and object value(annotation value)</returns>
57+
IDictionary<string, object> GetPropertyAnnotations(string propertyName);
58+
}
59+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License. See License.txt in the project root for license information.
3+
4+
using System.Reflection;
5+
using Microsoft.AspNet.OData.Common;
6+
using Microsoft.OData.Edm;
7+
8+
namespace Microsoft.AspNet.OData.Builder
9+
{
10+
/// <summary>
11+
/// This annotation indicates the mapping from a <see cref="IEdmStructuredType"/> to a <see cref="PropertyInfo"/>.
12+
/// The <see cref="IEdmStructuredType"/> is a type of IODataInstanceAnnotationContainer and the <see cref="PropertyInfo"/> is the specific
13+
/// property which is used to save/retrieve the instance annotations.
14+
/// </summary>
15+
internal class ODataInstanceAnnotationContainerAnnotation
16+
{
17+
/// <summary>
18+
/// Initializes a new instance of <see cref="ODataInstanceAnnotationContainerAnnotation"/> class.
19+
/// </summary>
20+
/// <param name="propertyInfo">The backing <see cref="PropertyInfo"/>.</param>
21+
public ODataInstanceAnnotationContainerAnnotation(PropertyInfo propertyInfo)
22+
{
23+
if (propertyInfo == null)
24+
{
25+
throw Error.ArgumentNull("propertyInfo");
26+
}
27+
28+
TypeHelper.ValidateAssignableFromForArgument(typeof(IODataInstanceAnnotationContainer), propertyInfo.PropertyType, "IODataInstanceAnnotationContainer");
29+
30+
PropertyInfo = propertyInfo;
31+
}
32+
33+
/// <summary>
34+
/// Gets the <see cref="PropertyInfo"/> which backs the instance annotations of the clr type/resource etc.
35+
/// </summary>
36+
public PropertyInfo PropertyInfo
37+
{
38+
get;
39+
}
40+
}
41+
}

src/Microsoft.AspNet.OData.Shared/Builder/ODataConventionModelBuilder.cs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -557,6 +557,10 @@ private void MapStructuralType(StructuralTypeConfiguration structuralType)
557557
{
558558
structuralType.AddDynamicPropertyDictionary(property);
559559
}
560+
else if (propertyKind == PropertyKind.InstanceAnnotations)
561+
{
562+
structuralType.AddInstanceAnnotationContainer(property);
563+
}
560564
else
561565
{
562566
// don't add this property if the user has already added it.
@@ -700,6 +704,16 @@ private PropertyKind GetPropertyType(PropertyInfo property, out bool isCollectio
700704
return PropertyKind.Dynamic;
701705
}
702706

707+
// IODataInstanceAnnotationContainer is used as a container to save/retrieve instance annotation properties for a CLR type.
708+
// It is different from other collections (for example, IDictionary<string,IDictionary<string, int>>)
709+
if (typeof(IODataInstanceAnnotationContainer).IsAssignableFrom(property.PropertyType))
710+
{
711+
mappedType = null;
712+
isCollection = false;
713+
714+
return PropertyKind.InstanceAnnotations;
715+
}
716+
703717
PropertyKind propertyKind;
704718
if (TryGetPropertyTypeKind(property.PropertyType, out mappedType, out propertyKind))
705719
{

0 commit comments

Comments
 (0)