3

我想得到一些OO正确的建议。从继承的类中访问属性数据的正确方法是什么。

假设3类:

public abstract class Vehicle
{
  public int Id {get; set; }    
  public int Wheels {get; set; }
  public string Name {get; set; }
  public string Color {get; set; }
 }
 public class Car : Vehicle
 {
 }
 public class Truck : Vehicle
 {
  public int LoadCapacity {get; set; }  
 }

我的第一个想法是创建某种类型的存储库,为我提供我正在寻找的任何东西的属性。

在我看来,我需要两种类型的查询:

  1. 返回具有特定 ID 的车辆的属性
  2. 给我所有特定类型的车辆

所以:

public class VehicleRepository
{
    ICollection <???> _vehicles;

    ??? GetVehicle(int Id);
    ??? GetVehicles(??? vehicleType);
}

这 ???是我的未知数。

我的想法是添加类似 IVehicle 的接口并用它实现 Vehicle 的东西。结果将是这样的:

public class VehicleRepository
{
    ICollection <IVehicle> _vehicles;

    IVehicle GetVehicle(int Id);
    ICollection <IVehicle> GetVehicles(IVehicle vehicleType);
}

这显然行不通。

public IVehicle GetVehicle(int Id)
{
    return _vehicles.First(x=>x.Id == Id);
    // The above want compile as the interface has no attributes
}

如果我使用 Vehicle 而不是 IVehicle,则“First(x=>x.Id == Id)”会正常工作,但如果车辆是卡车,它将不会返回“LoadCapacity”。

查看 GetVehicles 函数,我在想:

public ICollection <T> GetVehicles <T> ()
{
    var vehicles = _vehicles.Where(???);
    return vehicles;
}

有点迷失在那里应该去,但我想避免反射,只是阅读程序集和类类型等。

感谢您的任何建议。

4

2 回答 2

3

要存储和获取 Vericles,您需要做的就是:

class VehicleRepository {
    List<Vehicle> vehicles;
}

要检索它们,只需使用IEnumerable<T>.OfType<U>()

VehicleRepository repository = ...
repository.vehicles.OfType<Car>(); // This will get you all of the cars
repository.vehicles.OfType<Truck>(); // This will get you all of the trucks

但是,如果您想变得花哨,则可以通过实现VehicleRepositorya 来使集合成为自己的集合IEnumerable<T>。考虑:

class VehicleRepository : IEnumerable<Vehicle> {
    List<Vehicle> vehicles;

    public IEnumerator<Vehicle> GetEnumerator() {
        return vehicles.GetEnumerator();
    }

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
        return this.GetEnumerator();
    }
}

然后您可以查询集合本身,如下所示:

public static void Main() {
    VehicleRepository repository = ...;

    // Notice that we skip accessing the vehicles member
    // because by implementing IEnumerable<T> this class
    // becomes a collection. Now you can use OfType<T> directly.
    repository.OfType<Car>(); 
}

编辑:要做类似的事情GetVehicleByID,你可以尝试这样的事情:

class VehicleRepository : IEnumerable<Vehicle> {
    List<Vehicle> vehicles;

    public Vehicle GetVehicleByID(Int32 id) {
        return vehicles[id];
    }
}

您还可以使用索引器,如下所示:

class VehicleRepository : IEnumerable<Vehicle> {
    List<Vehicle> vehicles;

    public Vehicle this[Int32 id] {
        get { return vehicles[id]; }
    }
}

要从LoadCapacity卡车上下来,您所要做的就是这样:

public static void Main() {
   VehicleRepository repository = ...

   // Assuming index zero is a truck
   Truck truck = (Truck)repository.GetVehicleByID(0);
   truck.LoadCapacity = ...
}

在不使用反射的情况下获取特定类型的所有项目(当绑定到 UI 时,即假设您正在使用Strings)的一种欺骗方法是匹配ToString类型名称的值。例如:

public static void Main() {
   VehicleRepository repository = ...

   // Assume we're storing off the typename in the UI dropdown.
   // so that when the user selects it, we automatically have the correct
   // type name we want to filter by.
   String truckTypeName = typeof(Truck).GetType().ToString();      

   // Filter only by those types with a matching type name. Inefficient,
   // but it does avoid reflection.
   repository.Where(vehicle => vehicle.GetType().ToString() == truckTypeName)
}
于 2013-10-06T16:06:59.207 回答
0

您可以使用该OfType方法获取特定类型集合中的项目:

public ICollection<T> GetVehicles<T>() {
  return _vehicles.OfType<T>();
}
于 2013-10-06T16:07:30.460 回答