skip to Main Content

I want to use the ASP.NET [Range] Annotation but for the elements IEnumerables.

I used the existing RangeAttribute like this:

public class RangeEnumerable : RangeAttribute
{
    /// <inheritdoc/>
    public RangeEnumerable(double minimum, double maximum) : base(minimum, maximum)
    {
    }

    /// <inheritdoc/>
    public RangeEnumerable(int minimum, int maximum) : base(minimum, maximum)
    {
    }

    /// <inheritdoc/>
    public RangeEnumerable([DynamicallyAccessedMembers((DynamicallyAccessedMemberTypes)(-1))] Type type, string minimum, string maximum) : base(type, minimum, maximum)
    {
    }

    /// <inheritdoc/>
    public override bool IsValid(object? value)
    {
        if (null == value) { return true; } 

        IEnumerable<object> list = ((IEnumerable)value).Cast<object>();
        
        foreach (object item in list)
        {
            if (!base.IsValid(item))
            {
                return false;
            }                
        }

        return true;
    }
}

and annotated my Parameter like this:

[RangeEnumerable(MINIMUM_ANGLE, MAXIMUM_ANGLE)]
public IEnumerable<Double> PhaseAnglesVoltage { get; set; } = new List<double>();

And wrote the following unit test:

[Test]
public void TestInvalidPhaseAngleVoltageTooLow()
{
    // Arrange       
    Loadpoint loadpoint1 = new Loadpoint();
    loadpoint1.PhaseAnglesVoltage.Append(-1);

    // Act
    var errCount = ValidateObject(loadpoint1);

    // Assert
    Assert.AreEqual(1, errCount);
}

private int ValidateObject(object obj)
{
    var validationContext = new ValidationContext(obj, null, null);
    var validationResults = new List<ValidationResult>();
    Validator.TryValidateObject(obj, validationContext, validationResults, true);
    return validationResults.Count;
}

I expected the loop to iterate over the elements of the List I used the annotation with, but in the IsValid-Function I always get an empty List instead of one with the element appended in the test.

2

Answers


  1. Chosen as BEST ANSWER

    Ok, I've found the error, which was in the unit test. IEnumerable.Append doesn't add the element to the original object like List.Add does (see Difference between a List's Add and Append method?).

    Changing the unit test to the following does the trick.

            [Test]
            public void TestInvalidPhaseAngleVoltageTooLow()
            {
                // Arrange       
                Loadpoint loadpoint1 = new Loadpoint();
                loadpoint1.PhaseAnglesVoltage = loadpoint1.PhaseAnglesVoltage.Append(-1);
    
                // Act
                var errCount = ValidateObject(loadpoint1);
       
                // Assert
                Assert.AreEqual(1, errCount);
            }
    

  2. I created one console app based on your code.

    enter image description here

    on line no 8 as you can see and as you said it does not change the source. But after modifying to below line will create another object from that yielded IEnumerable

    model.Doubles = model.Doubles.Append(1.1).toList();
    

    enter image description here

    I think the change you made is not working as expected. You need to do toList() or assign IEnumerable with new List() and then use Add() method of List which will change the source.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search