Skip to content

Commit 66dd5c4

Browse files
Add odata type to complex types for .Net and PHP (#154)
* Added code to generate compexTypes with odataType property * Add the @odata.type property to all base classes and set the ODataType on all non-abstract complex types. * Only create a constructor that initializes the ODataType when the complexType's base class is abstract, and that abstract base class is referenced as the type of a property in the OdcmModel. We need this change so that we can automatically set the ODataType when the service can't infer the type by the payloads content. * Updated PHP template to support setting ODataType when initializing an object that is descended from an abstract base.
1 parent 67e3c55 commit 66dd5c4

File tree

3 files changed

+58
-1
lines changed

3 files changed

+58
-1
lines changed

Templates/CSharp/Model/ComplexType.cs.tt

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,17 @@ namespace <#=complex.Namespace.GetNamespaceName()#>
4242
<#=attributeStringBuilder.ToString()#>
4343
public <#=classType#> <#=typeDeclaration#>
4444
{
45-
<#
45+
<#
46+
// Generate a constructor to initialize the @odata.type property when this type is not abstract and if this
47+
// type's base is abstract and the base is referenced as the type of a structural property. We need this
48+
// to disambiguate the type of the descendant class being sent.
49+
if (complex.IsBaseAbstractAndReferencedAsPropertyType() && !complex.IsAbstract)
50+
{
51+
#> public <#=complexTypeName#>()
52+
{
53+
this.ODataType = "<#=complex.FullName#>";
54+
}<#
55+
}
4656
foreach(var property in complex.Properties)
4757
{
4858

@@ -86,6 +96,7 @@ namespace <#=complex.Namespace.GetNamespaceName()#>
8696
}
8797

8898
// Only include AdditionalData in the base classes.
99+
// Adding odata.type to all complex types with no base class.
89100
if (complex.Base == null)
90101
{
91102
#>
@@ -95,6 +106,12 @@ namespace <#=complex.Namespace.GetNamespaceName()#>
95106
/// </summary>
96107
[JsonExtensionData(ReadData = true)]
97108
public IDictionary<string, object> AdditionalData { get; set; }
109+
110+
/// <summary>
111+
/// Gets or sets @odata.type.
112+
/// </summary>
113+
[JsonProperty(NullValueHandling = NullValueHandling.Ignore, PropertyName = "@odata.type", Required = Newtonsoft.Json.Required.Default)]
114+
public string ODataType { get; set; }
98115
<#
99116
}
100117
#>

Templates/PHP/Model/ComplexType.php.tt

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,22 @@ class <#=complexName.ToCheckedCase()#> extends Entity
2727
#>
2828
{
2929
<#
30+
// Generate a constructor to initialize the @odata.type property when this type is not abstract and if this
31+
// type's base is abstract and the base is referenced as the type of a structural property. We need this
32+
// to disambiguate the type of the descendant class being sent.
33+
if (complex.IsBaseAbstractAndReferencedAsPropertyType() && !complex.IsAbstract)
34+
{
35+
#> /**
36+
* Set the @odata.type since this type is immediately descended from an abstract
37+
* type that is referenced as the type in an entity.
38+
*/
39+
public function __construct()
40+
{
41+
$this->setODataType("#<#=complex.FullName#>");
42+
}
43+
44+
<#
45+
}
3046
foreach(var property in complex.Properties.Where(prop => prop.Type.GetTypeString() != "bytes")){
3147
var propertyName = property.Name.SanitizePropertyName(complexName);
3248
if (!property.Type.IsComplex()) {

src/GraphODataTemplateWriter/Extensions/OdcmModelExtensions.cs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,30 @@ public static string GetImplicitPropertyName(this OdcmProperty property, OdcmSin
223223
return implicitPropertyName;
224224
}
225225

226+
/// <summary>
227+
/// Indicates whether the abstract base class of a descendant is referenced as the type of a structural property.
228+
/// This has significance to scenarios where client needs to set the @odata.type property because the type cannot
229+
/// be inferred since the reference is the to abstract base class and the actual class used by the client is
230+
/// one of its descendants.
231+
/// </summary>
232+
/// <param name="complex">The ComplexType that we want to query whether its base type is the referenced type for any property in any entity.</param>
233+
/// <returns></returns>
234+
public static bool IsBaseAbstractAndReferencedAsPropertyType(this OdcmClass complex)
235+
{
236+
if (complex.Base == null)
237+
{
238+
return false;
239+
}
240+
else
241+
{
242+
return complex.Namespace.Types.Select(someType => (someType as OdcmEntityClass))
243+
.Where(someType => someType is OdcmEntityClass)
244+
.Where(someType => (someType as OdcmEntityClass).Properties
245+
.Any(x => x.Type.Name == complex.Base.Name && complex.Base.IsAbstract))
246+
.Any();
247+
}
248+
}
249+
226250
public static IEnumerable<OdcmProperty> NavigationProperties(this OdcmClass odcmClass)
227251
{
228252
return odcmClass.Properties.Where(prop => prop.IsNavigation());

0 commit comments

Comments
 (0)