【问题标题】:List with multiple derived object. How to acces the fields in the derived具有多个派生对象的列表。如何访问派生的字段
【发布时间】:2019-05-03 23:21:48
【问题描述】:

目前我正在使用一个名为 “JourneyLeg” 的基类。这个基类有 5 个派生的,它们都继承自基类。其中两个类称为 "WalkingLeg""VehicleLeg"。这 2 个派生类都包含一个 "from""to" 字段。其他 3 个没有。

List<JourneyLeg> legs

我现在有一个列表,其中包含所有类型的派生对象。其中一些是Walkingleg,其中一些是车辆腿,其余的是其他3 个派生类之一。列表定义如上。

我想遍历完整列表并仅对步行和车辆对象执行操作。这些操作包括访问“from”和“to”。这 2 个字段仅在这 2 个派生类中可用,在基类中不可用。

我能想到的唯一方法是检查它是否是 2 个派生类之一,然后执行操作(见下文)。但是这样我就有很多重复的代码。我认为我无法在方法中提取重复代码,因为我们为该方法提供的参数对象将是 VehicleLeg 或 WalkingLeg 并且不能两者兼而有之。

case VehicleLeg vehicleLeg:
{
    var legTo = new DirectionsRequestJourneyLegsLocation(vehicleLeg.To.LatLong, vehicleLeg.To.IsVisible);
    var legFrom = new DirectionsRequestJourneyLegsLocation(vehicleLeg.From.LatLong, vehicleLeg.From.IsVisible);

    directionsRequestJourneyleg.id = vehicleLeg.Id;
    directionsRequestJourneyleg.From = legFrom;
    directionsRequestJourneyleg.To = legTo;
    directionsRequestJourneyleg.LegArrival = vehicleLeg.From.Time.Planned;
    directionsRequestJourneyleg.LegDeparture = vehicleLeg.To.Time.Planned;

    directionsRequestJourneyleg.Type = DirectionsRequestJourneyLegType.Vehicle;
    directionsRequestJourneyleg.Modality = vehicleLeg.Modality;
    break;
}
case WalkingLeg walkingLeg:
{
    var legTo = new DirectionsRequestJourneyLegsLocation(walkingLeg.To.LatLong, walkingLeg.To.IsVisible);
    var legFrom = new DirectionsRequestJourneyLegsLocation(walkingLeg.From.LatLong, walkingLeg.From.IsVisible);


    directionsRequestJourneyleg.id = walkingLeg.Id;
    directionsRequestJourneyleg.From = legFrom;
    directionsRequestJourneyleg.To = legTo;
    directionsRequestJourneyleg.LegArrival = walkingLeg.From.Time.Planned;
    directionsRequestJourneyleg.LegDeparture = walkingLeg.To.Time.Planned;
    directionsRequestJourneyleg.Type = DirectionsRequestJourneyLegType.Walking;
    break;
}

我可能在这里遗漏了一些简单的东西。但我无法绕过它。我希望有人能让我重回正轨。

以下是课程:

/// <summary>
/// JourneyLeg is the base class used to define commonalities between:
/// 
/// *VehicleLeg, WalkingLeg, TransitionLeg, AdvertisementLeg*
/// </summary>
public class JourneyLeg
{
    [Required]
    public string Id { get; set; }
    [Required]
    public LegType Type { get; set; }
}
/// <summary>
/// Vehicle leg model
/// </summary>
public class VehicleLeg : JourneyLeg
{
    [Required]
    public ModalityType Modality { get; set; }
    [Required]
    public LegStop From { get; set; }
    [Required]
    public LegStop To { get; set; }
}
/// <summary>
/// Walking leg model
/// </summary>
public class WalkingLeg : JourneyLeg
{
    [Required]
    public LegStop From { get; set; }
    [Required]
    public LegStop To { get; set; }
    /// <summary>
    /// Displays the total walk time in minutes and in parenthese the distance in meters
    /// </summary>
    [Required]
    public string Description { get; set; }
}

【问题讨论】:

  • 最好使用接口继承而不是类继承——类上可以有多个接口(例如 Leg 和 Arm 可以有 IVehicle 接口,但它们有分离的 ILeg 和 IArm 接口)

标签: c# derived-class base-class


【解决方案1】:

创建一个新类JourneyLegFromTo 或类似的继承JourneyLeg,然后使VehicleLegWalkingLeg 从新类继承。

然后您可以将代码简化为检查它是否为JouneyLegFromTo 而不是这两种情况,并且您将能够访问 from 和两个字段。

public class JourneyLegFromTo : JourneyLeg
{
    [Required]
    public LegStop From { get; set; }
    [Required]
    public LegStop To { get; set; }
}

public class WalkingLeg : JourneyLegFromTo 
{
    ...
}

public class VehicleLeg : JourneyLegFromTo 
{
    ...
}

稍后:

case JourneyLegFromTo journeyLegFromTo:
{
    var legTo = new DirectionsRequestJourneyLegsLocation(journeyLegFromTo.To.LatLong, journeyLegFromTo.To.IsVisible);
    var legFrom = new DirectionsRequestJourneyLegsLocation(journeyLegFromTo.From.LatLong, journeyLegFromTo.From.IsVisible);
    ...

【讨论】:

  • 请注意:我在答案中添加了完整开关,因为 caseWalkingLegVehicleLeg 的特定内容结尾
【解决方案2】:

我只需要添加一个中间类来添加FromTo 属性:

public class JourneyLeg
{
    [Required]
    public string Id { get; set; }

    [Required]
    public LegType Type { get; set; }
}

// You may want another name...
public class JourneyFromToLeg : JourneyLeg
{
    [Required]
    public LegStop From { get; set; }

    [Required]
    public LegStop To { get; set; }
}

public class VehicleLeg : JourneyFromToLeg 
{
    [Required]
    public ModalityType Modality { get; set; }
}

public class WalkingLeg : JourneyFromToLeg 
{
    [Required]
    public string Description { get; set; }
}

所以你可以使用:

case JourneyFromToLeg fromToLeg:
{
    var legTo = new DirectionsRequestJourneyLegsLocation(fromToLeg.To.LatLong, fromToLeg.To.IsVisible);
    var legFrom = new DirectionsRequestJourneyLegsLocation(fromToLeg.From.LatLong, fromToLeg.From.IsVisible);


    directionsRequestJourneyleg.id = fromToLeg.Id;
    directionsRequestJourneyleg.From = legFrom;
    directionsRequestJourneyleg.To = legTo;
    directionsRequestJourneyleg.LegArrival = fromToLeg.From.Time.Planned;
    directionsRequestJourneyleg.LegDeparture = fromToLeg.To.Time.Planned;

    // you may want to think a little more of this too
    if (fromToLeg is WalkingLeg)
    {
        directionsRequestJourneyleg.Type = DirectionsRequestJourneyLegType.Walking;
    }
    else
    {
        directionsRequestJourneyleg.Type = DirectionsRequestJourneyLegType.Vehicle;
        directionsRequestJourneyleg.Modality = ((VehicleLeg)fromToLeg).Modality;            
    }

    break;
}

如果您更喜欢使用接口继承,则可以使用 IFromLeg/IToLeg/IFromToLeg 接口

【讨论】:

  • 我正在实施这个答案,但仍然有问题。查看我的代码并得出结论,该列表仅包含基本的 JourneyLeg 类对象。它是从“发布”的 JSON 在我的 Web 控制器中创建的,当然它不知道派生类只知道基类。我想我必须检查字段并创建一个新对象。还是要检查答案是否正确,这个答案肯定会对上述问题有所帮助。
猜你喜欢
  • 1970-01-01
  • 2021-11-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-17
  • 2018-02-11
相关资源
最近更新 更多