Skip to content

Add support for derived type constraint annotation - #1977

Merged
KanishManuja-MS merged 3 commits into
OData:masterfrom
KanishManuja-MS:Add-derived-type-constraint
Apr 15, 2020
Merged

Add support for derived type constraint annotation#1977
KanishManuja-MS merged 3 commits into
OData:masterfrom
KanishManuja-MS:Add-derived-type-constraint

Conversation

@KanishManuja-MS

Copy link
Copy Markdown
Contributor

Issues

This pull request enables support for derived type constraint annotation.

Description

Non-convention model builder now has APIs and thus support for adding out of line annotations for derived type constraint.

Checklist (Uncheck if it is not completed)

  • Test cases added
  • Build and test with one-click build and test script passed

@KanishManuja-MS KanishManuja-MS changed the title Add derived type constraint Add support for derived type constraint annotation Dec 9, 2019
/// </summary>
public ActionConfiguration AddDerivedTypeConstraint<TSubClass>() where TSubClass : class
{
base.AddDerivedTypeConstraintToReturnTypeImplementation(typeof(TSubClass));

@xuzhg xuzhg Dec 16, 2019

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

base [](start = 12, length = 4)

"base. " is unnecessary? #Resolved

/// </summary>
public CollectionPropertyConfiguration AddDerivedTypeConstraint<TSubClass>() where TSubClass : class
{
this.AddDerivedTypeConstraintImpl(typeof(TSubClass));

@xuzhg xuzhg Dec 16, 2019

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this [](start = 12, length = 4)

"this." is unnecessary? #Resolved

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same for others


In reply to: 358414860 [](ancestors = 358414860)

/// <summary>
/// Adds TSubClass to the list of derived type constraints.
/// </summary>
public SingletonConfiguration AddDerivedTypeConstraint<TSubClass>() where TSubClass : class

@xuzhg xuzhg Dec 16, 2019

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AddDerivedTypeConstraint() [](start = 38, length = 37)

AddDerivedTypeConstraint() [](start = 38, length = 37)

For design perspective, add a non-generic method to support adding TypeConstraint.

Call the non-generic method in the generic method. #Resolved

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same for others.


In reply to: 358416790 [](ancestors = 358416790)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

somthing likes public SingletonConfiguration AddDerivedTypeConstraint(params Type type) {}


In reply to: 358416861 [](ancestors = 358416861,358416790)

@xuzhg

xuzhg commented Dec 16, 2019

Copy link
Copy Markdown
Member
  1. Add the non-generic mothed to support runtime configuration.
  2. Call non-generic method in your generic method
  3. Where's conventional model build supporting?
  4. Add the E2E test cases to verify the type constraint working, includes but not limits
    a) to verify ODL throw correct exception for non-supported type cast
    b) to verify the ODL throw correct exception for non-supported instance serialization #Resolved

private readonly Dictionary<PropertyInfo, IEdmProperty> _properties = new Dictionary<PropertyInfo, IEdmProperty>();
private readonly Dictionary<IEdmProperty, QueryableRestrictions> _propertiesRestrictions = new Dictionary<IEdmProperty, QueryableRestrictions>();
private readonly Dictionary<IEdmProperty, ModelBoundQuerySettings> _propertiesQuerySettings = new Dictionary<IEdmProperty, ModelBoundQuerySettings>();
private readonly Dictionary<IEdmProperty, PropertyConfiguration> _propertyConfigurations = new Dictionary<IEdmProperty, PropertyConfiguration>();

@xuzhg xuzhg Dec 16, 2019

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_propertyConfigurations [](start = 73, length = 23)

We can't use the "_properties" field? #Resolved

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need PropertyConfiguration. _properties does not have any configuration.


In reply to: 358418941 [](ancestors = 358418941)

if (types.Count == 0)
{
return;
}

@xuzhg xuzhg Dec 16, 2019

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

switch line 689 and ling 690 #Resolved

}
else
{
throw Error.InvalidOperation("Cannot find EdmType corresponding to {0}", type);

@xuzhg xuzhg Dec 16, 2019

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cannot find EdmType corresponding to {0} [](start = 50, length = 40)

use the SRSources for the error message? #Resolved

return;
}

List<EdmStringConstant> collectionConstants = new List<EdmStringConstant>();

@xuzhg xuzhg Dec 16, 2019

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

List collectionConstants = new List(); [](start = 12, length = 76)

shall we make sure no duplicated existed? #Resolved

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We do that through the ISet. At this point in time, there should be no duplicates.


In reply to: 358420621 [](ancestors = 358420621)

using System.Diagnostics.CodeAnalysis;
using System.Diagnostics.Contracts;
using System.Linq;
using System.Reflection;

@xuzhg xuzhg Dec 16, 2019

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

move System.* ahead #Resolved

_bindingParameter = new BindingParameterConfiguration(name, bindingParameterType);
}

internal virtual void AddDerivedTypeConstraintToReturnTypeImplementation(Type t)

@xuzhg xuzhg Dec 16, 2019

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

t [](start = 85, length = 2)

rename the parameter name #Resolved

_bindingParameter = new BindingParameterConfiguration(name, bindingParameterType);
}

internal virtual void AddDerivedTypeConstraintToReturnTypeImplementation(Type t)

@xuzhg xuzhg Dec 16, 2019

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

virtual [](start = 17, length = 7)

I don't think it's virtual method, right? #Resolved

{
if (ReturnType.ClrType == null)
{
throw Error.InvalidOperation("No CLR Type specified for this configuration.");

@xuzhg xuzhg Dec 16, 2019

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No CLR Type specified for this configuration. [](start = 46, length = 45)

centralize the error messages #Resolved


internal virtual void AddDerivedTypeConstraintToReturnTypeImplementation(Type t)
{
if (ReturnType.ClrType == null)

@xuzhg xuzhg Dec 16, 2019

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ReturnType [](start = 16, length = 10)

ReturnType maybe "null", right? #Resolved

_bindingParameter = new BindingParameterConfiguration(name, bindingParameterType);
}

internal virtual void AddDerivedTypeConstraintToReturnTypeImplementation(Type t)

@xuzhg xuzhg Dec 16, 2019

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Type t [](start = 81, length = 6)

t maybe null #Resolved


if (TypeConfiguration.ClrType == null)
{
throw Error.InvalidOperation("No CLR Type specified for this configuration.");

@xuzhg xuzhg Dec 16, 2019

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No CLR Type specified for this configuration. [](start = 46, length = 45)

centralize the error messages #Resolved


DerivedTypeConstraints.Add(t);
return this;
}

@xuzhg xuzhg Dec 16, 2019

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems similar method repeated a lot, maybe consider to create a helper method #Resolved


[Fact]

public async Task VerifyMetaDataIsGeneratedCorrectly()

@xuzhg xuzhg Dec 16, 2019

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

VerifyMetaDataIsGeneratedCorrectly() [](start = 26, length = 36)

Add test cases in "MetadataControllerTest.cs" to verify the annotation showing in the xml #Resolved

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

need E2E test cases to verify:

  1. Uri parsing
  2. Serialization

In reply to: 358425347 [](ancestors = 358425347)

}

var collectionExpression = new EdmCollectionExpression(collectionConstants);
EdmVocabularyAnnotation annotation = new EdmVocabularyAnnotation(target, term, collectionExpression);

@xuzhg xuzhg Dec 16, 2019

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

EdmVocabularyAnnotation annotation = new EdmVocabularyAnnotation(target, term, collectionExpression); [](start = 12, length = 101)

Discussion: Maybe need configuration to set the annotation location (Inline or outofLine) #Resolved

public QueryConfiguration QueryConfiguration { get; set; }

/// <summary>
/// Adds TSubClass to the list of derived type constraints.

@xuzhg xuzhg Jan 2, 2020

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TSubClass [](start = 17, length = 9)

TSubClass [](start = 17, length = 9)

resentence the comments #Resolved

/// </summary>
internal PropertyConfiguration AddDerivedTypeConstraintImpl(Type t)
{
if (RelatedClrType == null)

@xuzhg xuzhg Jan 2, 2020

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

RelatedClrType [](start = 16, length = 14)

why do we test this? It should be tested on the constructor, right? #Resolved

{
if (RelatedClrType == null)
{
throw Error.InvalidOperation("No CLR Type specified for this configuration.");

@xuzhg xuzhg Jan 2, 2020

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No CLR Type specified for this configuration. [](start = 46, length = 45)

add the errors into resource manage #Resolved

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same for other


In reply to: 362588158 [](ancestors = 362588158)

/// <summary>
/// Adds TSubClass to the list of derived type constraints.
/// </summary>
internal PropertyConfiguration AddDerivedTypeConstraintImpl(Type t)

@xuzhg xuzhg Jan 2, 2020

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

t [](start = 73, length = 1)

rename the parameter name #Resolved

/// </summary>
public SingletonConfiguration AddDerivedTypeConstraint<TSubClass>() where TSubClass : class
{
this.AddDerivedTypeConstraintImpl(typeof(TSubClass));

@xuzhg xuzhg Jan 2, 2020

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this. [](start = 12, length = 5)

don't need "this." #Resolved

/// </summary>
internal void AddDerivedTypeConstraintImpl(Type t)
{
if (ClrType == null)

@xuzhg xuzhg Jan 2, 2020

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if (ClrType == null) [](start = 12, length = 20)

we don't need to test this, right?
It's verify at the constuctor #Resolved

/// </summary>
public NavigationPropertyConfiguration AddDerivedTypeConstraint<TSubClass>() where TSubClass : class
{
this.AddDerivedTypeConstraintImpl(typeof(TSubClass));

@xuzhg xuzhg Jan 2, 2020

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove "this." #Resolved

/// <summary>
/// Adds TSubClass to the list of derived type constraints.
/// </summary>
public EnumPropertyConfiguration AddDerivedTypeConstraint<TSubClass>() where TSubClass : class

@xuzhg xuzhg Jan 2, 2020

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

EnumPropertyConfiguration [](start = 15, length = 25)

do we have the enum property derived type scenario? #Resolved

/// </summary>
public EntitySetConfiguration AddDerivedTypeConstraint<TSubClass>() where TSubClass : class
{
this.AddDerivedTypeConstraintImpl(typeof(TSubClass));

@xuzhg xuzhg Jan 2, 2020

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this. [](start = 12, length = 5)

remove this. #Resolved

/// </summary>
public ComplexPropertyConfiguration AddDerivedTypeConstraint<TSubClass>() where TSubClass : class
{
this.AddDerivedTypeConstraintImpl(typeof(TSubClass));

@xuzhg xuzhg Jan 2, 2020

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this. [](start = 12, length = 5)

remove this. #Resolved

@xuzhg xuzhg left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🕐

public DerivedTypeConstraintSet(Type baseType)
: base()
{
ClrBaseType = baseType;

@xuzhg xuzhg Mar 18, 2020

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ClrBaseType = baseType; [](start = 12, length = 23)

no config for the Location? #Resolved

/// <summary>
/// Initializes a DerivedTypeConstraintSet instance without setting a base type.
/// </summary>
public DerivedTypeConstraintSet()

@xuzhg xuzhg Mar 18, 2020

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DerivedTypeConstraintSet [](start = 15, length = 24)

maybe call other ctor with arguments #Resolved

public DerivedTypeConstraintSet(Type baseType)
: base()
{
ClrBaseType = baseType;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ClrBaseType = baseType; [](start = 12, length = 23)

check the baseType nullable?

{
ValidateAndAddSingleConstraint(ClrBaseType);
return;
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if the input is empty, add the ClrBaseType ? Why don't we have this strange logic?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had two options; One was to throw an error and the other was to consider that as an indication to allow only base types. Consider that this is called from HasDerivedTypeConstraints(). What should be the behavior?


In reply to: 394506704 [](ancestors = 394506704)

if (ClrBaseType == null)
{
throw Error.InvalidOperation(SRResources.NoClrTypeSpecified);
}

@xuzhg xuzhg Mar 18, 2020

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A DerivedTypeConstraintSet should have a ClrBaseType configuired already, why should we check this? #ByDesign

@KanishManuja-MS KanishManuja-MS Mar 18, 2020

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

An operation can be created without a ClrBaseType. Think about actions with no return type. #ByDesign

throw Error.InvalidOperation(SRResources.ConstraintAlreadyExists, typeToAdd.Name);
}
}
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd like to copy/paste my assumption:
I don't want to use my name, but, for the "Add" logic, we can make it simple as blow

/// <summary>
/// 
/// </summary>
public class DerivedTypeConstraintConfiguration
{
    private ISet<Type> _derivedTypes;

    /// <summary>
    /// 
    /// </summary>
    /// <param name="baseType"></param>
    public DerivedTypeConstraintConfiguration(Type baseType)
    {
        ClrBaseType = baseType;
        _derivedTypes = new HashSet<Type>();
        Location = EdmVocabularyAnnotationSerializationLocation.OutOfLine;
    }

    /// <summary>
    /// 
    /// </summary>
    public ISet<Type> DerivedTypes { get { return _derivedTypes; } }

    /// <summary>
    /// 
    /// </summary>
    public Type ClrBaseType { get; private set; }

    /// <summary>
    /// 
    /// </summary>
    /// <typeparam name="TDerived"></typeparam>
    public void Add<TDerived>()
    {
        Add(typeof(TDerived));
    }

    /// <summary>
    /// 
    /// </summary>
    public EdmVocabularyAnnotationSerializationLocation Location { get; set; }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="derivedType"></param>
    public void Add(Type derivedType)
    {
        if (derivedType == ClrBaseType)
        {
            return;
        }

        if (_derivedTypes.Contains(derivedType))
        {
            return;
        }

        if (!ClrBaseType.IsAssignableFrom(derivedType))
        {
            throw new Exception("blabla");
        }

        _derivedTypes.Add(derivedType);
    }
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The main difference that I see is that you don't support adding enumerables. I think it makes the implementation a lot cleaner if you can add enumerables to the set.


In reply to: 394509903 [](ancestors = 394509903)

/// <summary>
/// Set of derived type constraints.
/// </summary>
public class DerivedTypeConstraintSet : HashSet<Type>

@xuzhg xuzhg Mar 18, 2020

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

: HashSet [](start = 42, length = 15)

I am not fan for either "derived" or "Composition"

However, i'd like to mention:

  1. Derived "HasSet" , we can't change later for this type owing breaking changes.
  2. Composition and make it private means we can change it any time without any breaking changes.

#Resolved

_returnType = value;
if (value != null)
{
DerivedTypeConstraints.ClrBaseType = value.ClrType;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DerivedTypeConstraints.ClrBaseType = value.ClrType; [](start = 20, length = 51)

That's weird and change/add the configuration even no derived type configuration happens in customer scenarios

@KanishManuja-MS KanishManuja-MS Mar 27, 2020

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The option was to lazy initialize and save extra allocations or initialize with the constructor. Model builder not being the most performance critical piece, I decided to initialize with the constructor. Since the return type does not have to be specified in the operation configuration initialization,I need to update it for the derivedTypeConstraint whenever it gets set. Will change to lazy initialize for operations.


In reply to: 394512858 [](ancestors = 394512858)

/// </summary>
/// <param name="subtypes">The subtypes for which the constraint needs to be added.</param>
/// <returns>Updated configuration object.</returns>
public ActionConfiguration HasDerivedTypeConstraints(params Type[] subtypes)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

HasDerivedTypeConstraints [](start = 35, length = 25)

I can't understand which derived constraint happens if customer call this method.

It's for the Binding type constraint, or return type constraint.

Be caution, return type and binding type could be the same type.

@KanishManuja-MS KanishManuja-MS Mar 18, 2020

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is for the return type, I changed the name to be more explicit. I don't think we should give customers two ways of doing one thing. The can always do function.BindingParameter.HasDerivedTypeConstraint().

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/// <summary>
/// Represents an <see cref="Attribute"/> that can be placed on a property or placed on a class to specify the derived type constraints.
/// </summary>
[AttributeUsage(AttributeTargets.Property)]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[AttributeUsage(AttributeTargets.Property)] [](start = 4, length = 43)

It's only for the property, we can't put it on the class?

My assumption is like this:

[DerivedTypeConstraint(typeof(Human)]
[DerivedTypeConstraint(typeof(Dog)]
....
public class Creature
{
    ....
}

It support to multiple config, each for one. (I am also ok to use param[])

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you start putting it on Classes, user will expect to put constraints on entity types which we don't want to do. And Params seems cleaner.


In reply to: 394517334 [](ancestors = 394517334)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SO, we don't have the C# attribute for entity set?
can we do like this:

And a string argument into the Constructor of "DerivedTypeConstraintAttribute", use it to set the entity set or singleton or navigation property built from this type?

[DerivedTypeConstraint(typeof(Human), "Creatures"]
[DerivedTypeConstraint(typeof(Dog)]
....
public class Creature
{
....
}


In reply to: 399119699 [](ancestors = 399119699,394517334)

public DerivedTypeConstraintAttribute()
{
DerivedTypeConstraints = new HashSet<Type>();
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do we have a empty here?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Required by the compiler. Need to have at least one constructor with CLS compliant parameters for these classes.


In reply to: 394517978 [](ancestors = 394517978)

{
throw Error.InvalidOperation(SRResources.NoClrTypeSpecified);
}
else if (!ClrBaseType.IsAssignableFrom(typeToAdd) && typeToAdd != ClrBaseType)

@mikepizzo mikepizzo Mar 19, 2020

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

&& typeToAdd != ClrBaseType [](start = 62, length = 27)

I don't think you need this second check; if typeToAdd == ClrBaseType, then ClrBaseType.IssAssignableFrom(typeToAdd) would be true. #Resolved

/// <summary>
/// Initializes a DerivedTypeConstraintConfiguration instance without setting a base type.
/// </summary>
internal DerivedTypeConstraintConfiguration()

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

internal [](start = 8, length = 8)

why it's internal?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't want people to create a DerivedTypeConstraintConfiguration without a base type.


In reply to: 401810329 [](ancestors = 401810329)

ReturnTypeConstraints = new DerivedTypeConstraintConfiguration(ReturnType.ClrType);
}

ReturnTypeConstraints.AddConstraint<TDerivedType>();

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why don't you move all these codes into base class OperationConfiguration?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To avoid the cast while using the fluent APIs. I can have an internal implementation on operation configuration but it is only 3 lines of code.


In reply to: 401813407 [](ancestors = 401813407)

ReturnTypeConstraints = new DerivedTypeConstraintConfiguration(ReturnType.ClrType);
}

ReturnTypeConstraints.AddConstraints(subtypes);

@xuzhg xuzhg Apr 1, 2020

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why don't you move all these codes into base class OperationConfiguration? #Resolved

@KanishManuja-MS KanishManuja-MS Apr 2, 2020

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To avoid the cast while using the fluent APIs. I can have an internal implementation on operation configuration but it is only 3 lines of code.


In reply to: 401813541 [](ancestors = 401813541)

@xuzhg xuzhg left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🕐

}

/// <summary>
/// Initializes a DerivedTypeConstraintConfiguration instance without setting a base type.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

without setting a base type [](start = 70, length = 27)

copy/paste - this overload doe sspecify a base type

address pr comments

update method
@KanishManuja-MS
KanishManuja-MS force-pushed the Add-derived-type-constraint branch from 6e44b49 to 9d4efb5 Compare April 8, 2020 17:44
@mikepizzo

Copy link
Copy Markdown
Contributor

I think we'll ultimately want to put the validation as a rule in EdmModel.Validate -- there may be scenarios where we (or the user) want to turn off this validation. But okay with it here for now, since it's internal, unless we have to make additional changes for other reasons.

@mikepizzo mikepizzo left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:shipit:

@KanishManuja-MS
KanishManuja-MS requested a review from xuzhg April 13, 2020 16:38
}
}

internal ISet<Type> ConstraintSet { get; }

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

internal ISet ConstraintSet { get; } [](start = 8, length = 42)

cannot be private?

@xuzhg xuzhg left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:shipit:

@KanishManuja-MS
KanishManuja-MS merged commit a664c1c into OData:master Apr 15, 2020
xuzhg pushed a commit that referenced this pull request May 29, 2026
* Everything except properties.

Fix tests

Address PR comments

Remove Inline change due to a bug

* Address PR comments and take sam's input

parity between actions and functions

self review

Update tests

fix final set of issues

* Address PR comments

address pr comments

update method
pull Bot pushed a commit to ehtick/WebApi that referenced this pull request May 29, 2026
* Everything except properties.

Fix tests

Address PR comments

Remove Inline change due to a bug

* Address PR comments and take sam's input

parity between actions and functions

self review

Update tests

fix final set of issues

* Address PR comments

address pr comments

update method
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Ready for review Use this label if a pull request is ready to be reviewed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants