I've implemented a Vehicle service that is responsible for servicing vehicles such as cars and trucks:
public interface IVehicleService
{
void ServiceVehicle(Vehicle vehicle);
}
public class CarService : IVehicleService
{
void ServiceVehicle(Vehicle vehicle)
{
if (!(vehicle is Car))
throw new Exception("This service only services cars")
//logic to service the car goes here
}
}
I also have a vehicle service factory that is responsible for creating a vehicle service according to the type of vehicle passed in to the factory method:
public class VehicleServiceFactory
{
public IVehicleService GetVehicleService(Vehicle vehicle)
{
if (vehicle is Car)
{
return new CarService();
}
if (vehicle is Truck)
{
return new TruckService();
}
throw new NotSupportedException("Vehicle not supported");
}
}
The issue I had was with the CarService.ServiceVehicle
method. It's accepting a Vehicle
when ideally it should accept a Car
, as it knows that it will only service cars. So I decided to update this implementation to use generics instead:
public interface IVehicleService<T> where T : Vehicle
{
void ServiceVehicle(T vehicle);
}
public class CarService : IVehicleService<Car>
{
void ServiceVehicle(Car vehicle)
{
//this is better as we no longer need to check if vehicle is a car
//logic to service the car goes here
}
}
public class VehicleServiceFactory
{
public IVehicleService<T> GetVehicleService<T>(T vehicle) where T : Vehicle
{
if (vehicle is Car)
{
return new CarService() as IVehicleService<T>;
}
if (vehicle is Truck)
{
return new TruckService() as IVehicleService<T>;
}
throw new NotSupportedException("Vehicle not supported");
}
}
The issue I currently have is when calling this factory as follows:
var factory = new VehicleServiceFactory();
Vehicle vehicle = GetVehicle();
var vehicleService = factory.GetVehicleService(vehicle); // this returns null!
vehicleService.ServiceVehicle(vehicle);
GetVehicleService
returns null
, I guess because I'm passing in the base type Vehicle
into this method, so T
would evaluate to Vehicle
and it isn't possible to cast from CarService
(which implements IVehicleService<Car>
) to the effective return type which would be IVehicleService<Vehicle>
(please correct me if I'm wrong).
Would appreciate some guidance on how to resolve this.