What is an acceptable way to provide the correct value in a property that depends on other properties of the same class?

Say I have a class that has three properties, as shown below.

public class Travel
{
  public int MinAirportArrival { get; set; }
  public int MinFlightTime { get; set; }
  public int TotalTravelTime { get; set; }
}

TotalTravelTime should be at least the sum of MinAirportArrival and MinFlightTime, but could also be greater if there is a stop or something like that.

It is clear to me that I can put the logic in setter for TotalTravelTime.

My question is about changing MinFlightTime and MinAirportArrival. Is it right to expect that TotalTravelTime will be increased first, and if there were no exception, if one of the others makes an amount larger than TotalTravelTime?

What are my other options for managing this in a smart way?

, , ? , .


, , . , , , , , .

+3
5

, . .

, :

  • :

    public class Travel
    {
      public int MinAirportArrival { get; set; }
      public int MinFlightTime { get; set; }
      public int AdditionalTravelTime { get; set; }
      public int TotalTravelTime
      {
        get { return MinAirportArrival + MinFlightTime + AdditionalTravelTime; }
      }
    }
    

    , , TotalTravelTime , .

  • - , , , .

    public class Travel
    {
      public int MinAirportArrival { get; set; }
      public int MinFlightTime { get; set; }
      public int TravelTime { get; set; }
      public void Save()
      {
        // validate TravelTime > MinAirportArrival + MinFlightTime 
      }
    }
    
  • - .

    public class Travel
    {
      public int MinAirportArrival { get; private set; }
      public int MinFlightTime { get; private set; }
      public int TravelTime { get; private set; }
      public void UpdateTimes(
        int minAirportArrival, int minFlightTime, int travelTime)
      {
        // validate travelTime > minAirportArrival + minFlightTime 
        MinAirportArrival = minAirportArrival;
        MinFlightTime = minFlightTime;
        TravelTime = travelTime;
      }
    }
    
  • Travel , factory - .

    :

    public class Travel
    {
      public Travel(int minAirportArrival, int minFlightTime, int travelTime)
      {
        // validate travelTime > minAirportArrival + minFlightTime 
      }
      public int MinAirportArrival { get; }
      public int MinFlightTime { get; }
      public int TravelTime { get; }
    }
    

    Factory :

    public class Travel
    {
      public static Travel CreateTravel(
        int minAirportArrival, int minFlightTime, int travelTime)
      {
        // validate travelTime > minAirportArrival + minFlightTime 
        return new Travel(minAirportArrival, minFlightTime, travelTime);
      }
      private Travel(int minAirportArrival, int minFlightTime, int travelTime);
      public int MinAirportArrival { get; }
      public int MinFlightTime { get; }
      public int TravelTime { get; }
    }
    

    Builder:

    public class TravelBuilder
    {
      public int MinAirportArrival { get; set; }
      public int MinFlightTime { get; set; }
      public int TravelTime { get; set; }
      public Travel BuildTravel()
      {
        // validate TravelTime > MinAirportArrival + MinFlightTime 
        return new Travel(MinAirportArrival, MinFlightTime, TravelTime);
      }
    }
    

    .NET.

+7

TotalTravelTime , , , .

+1

, API ( API-, DataGridView ASP.NET MVC), - IDataErrorInfo. , (). - :

IDataErrorInfo dei = obj as IDataErrorInfo;
if(dei != null) {
    string err = dei.Error;
    if(!string.IsNullOrEmpty(err)) throw new SomeTypeOfException(err);
}

:

public class Travel : IDataErrorInfo
{
    public int MinAirportArrival { get; set; }
    public int MinFlightTime { get; set; }
    public int TotalTravelTime { get; set; }
    string IDataErrorInfo.this[string property] {
        get {
            switch (property) {
                case "TotalTravelTime":
                    if (TotalTravelTime < MinAirportArrival + MinFlightTime) {
                        return "not enough time blah";
                    }
                    break;
            }
            return "";
        }
    }
    string IDataErrorInfo.Error {
        get {
            StringBuilder sb = new StringBuilder();
            AppendError(ref sb, "MinAirportArrival");
            AppendError(ref sb, "MinFlightTime");
            AppendError(ref sb, "TotalTravelTime");
            return sb == null ? "" : sb.ToString();
        }
    }
    void AppendError(ref StringBuilder builder, string propertyName) {
        string error = ((IDataErrorInfo)this)[propertyName];
        if (!string.IsNullOrEmpty(error)) {
            if (builder == null) {
                builder = new StringBuilder(error);
            } else {
                builder.Append(error);
            }
        }
    }
}
+1

, , :

public class Travel
{
    private int minAirportArrival;
    private int minFlightTime;
    private int additionalTravelTime;

    public int MinAirportArrival
    { 
        get
        {
            return this.minAirportArrival;
        }
        set
        {
            ThrowOnImpossibleTimes(value, this.minFlightTime, this.additionalTravelTime);
            this.minAirportArrival = value;
        }
    }

    // other properties...

    private static void ThrowOnImpossibleTimes(int minAirportArrival, int minFlightTime, int additionalTravelTime)
    {
        // do check and eventually throw...
    }
}
0

One way to do this is to implement a validation method that validates a condition. The method will be called from the installer of each property and will throw an exception if the condition is not met

0
source

Source: https://habr.com/ru/post/1723741/


All Articles