Reputation: 107
I would like to get some OO correct advice please. What is the correct way of accessing attribute data from inherited classes.
Assuming 3 classes:
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; }
}
My first thought was to create a repository of some kind that gives me the attributes of whatever I'm looking for.
There are 2 types of queries as I see it that I will need:
So:
public class VehicleRepository
{
ICollection <???> _vehicles;
??? GetVehicle(int Id);
??? GetVehicles(??? vehicleType);
}
The ??? are my unknowns.
My thought was to add something like an interface for IVehicle and implement Vehicle with it. The result would be something like:
public class VehicleRepository
{
ICollection <IVehicle> _vehicles;
IVehicle GetVehicle(int Id);
ICollection <IVehicle> GetVehicles(IVehicle vehicleType);
}
This obviously doesnt work.
public IVehicle GetVehicle(int Id)
{
return _vehicles.First(x=>x.Id == Id);
// The above want compile as the interface has no attributes
}
If I use Vehicle instead of IVehicle, the 'First(x=>x.Id == Id)' will work fine but it will not return 'LoadCapacity' if the vehicle is a truck.
Looking at the GetVehicles function, I was thinking something like:
public ICollection <T> GetVehicles <T> ()
{
var vehicles = _vehicles.Where(???);
return vehicles;
}
A bit lost on what should go in there BUT I would like to avoid reflection and just reading assemblies and class types, etc.
Thanks for any advice.
Upvotes: 3
Views: 168
Reputation: 11439
To store and get vericles, all you would need to do is something like:
class VehicleRepository {
List<Vehicle> vehicles;
}
to retrieve them, simply use 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
If you wanted to get fancy though, you could make the VehicleRepository
a collection all its own by making it implement IEnumerable<T>
. Consider:
class VehicleRepository : IEnumerable<Vehicle> {
List<Vehicle> vehicles;
public IEnumerator<Vehicle> GetEnumerator() {
return vehicles.GetEnumerator();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
return this.GetEnumerator();
}
}
Then you can query against the collection itself, as in:
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>();
}
EDIT: To do something like GetVehicleByID
, you might try something like this:
class VehicleRepository : IEnumerable<Vehicle> {
List<Vehicle> vehicles;
public Vehicle GetVehicleByID(Int32 id) {
return vehicles[id];
}
}
you could also use an indexer, like so:
class VehicleRepository : IEnumerable<Vehicle> {
List<Vehicle> vehicles;
public Vehicle this[Int32 id] {
get { return vehicles[id]; }
}
}
To get LoadCapacity
from a truck, all you would have to do is something like this:
public static void Main() {
VehicleRepository repository = ...
// Assuming index zero is a truck
Truck truck = (Truck)repository.GetVehicleByID(0);
truck.LoadCapacity = ...
}
One cheaty way to get all items of a particular type (when bound to the UI, i.e. assuming you're using Strings
) without using reflection is to match the ToString
values of the Type names. For example:
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)
}
Upvotes: 3
Reputation: 700322
You can use the OfType
method to get the items in a collection of a specific type:
public ICollection<T> GetVehicles<T>() {
return _vehicles.OfType<T>();
}
Upvotes: 0