I'm struggling with generics and don't really know what I'm doing wrong.
This is my example:
public class Repository // Base-class for all repositories
{
public virtual int GetStatus()
{
return 0;
}
}
Repository is just a base class.
public class CarRepository : Repository // base-class for all car repositories
{
private object dataSource;
public override int GetStatus()
{
return dataSource.GetHashCode(); // dummy
}
public virtual int GetPrice(string carName)
{
if (carName.Equals("BMW", StringComparison.OrdinalIgnoreCase)) {
return 100;
}
return 50;
}
}
CarRepository simply provides basic methods to interact with cars.
public class HttpCarRepository : CarRepository // loads the car data from REST Api
{
private dynamic httpClient; // just as an example
public override int GetStatus()
{
return httpClient.IsConnected();
}
public override int GetPrice(string carName)
{
return httpClient.GetAsync("/rest/car/BMW").Result;
}
}
There might also be an DataBaseCarRepository that loads the data from a database. You get the point.
That's for the setup.
Now, I want to cache the results. To keep it generic, I've created this construct:
public interface ICache<TRepo> // Basic Cache Interface
where TRepo : Repository
{
TRepo Repository { get; set; }
}
public class CarCache : CarRepository, ICache<CarRepository>
{
public CarRepository Repository { get; set; }
private dynamic cache;
public CarCache(CarRepository repo)
{
this.Repository = repo;
}
public override int GetPrice(string carName)
{
if (!this.cache.Contains(carName)) {
this.cache.Add(carName, this.Repository.GetPrice(carName));
}
return cache[carName];
}
}
CarCache derives from the base class CarRepository to make it possible to override the methods. It also implements ICache<T> which provides a reference to an actual
implementation of CarRepository, such as HttpCarRepository.
Now I want to add the CarCache to a list of caches.
public class Manager
{
public List<ICache<Repository>> Caches;
}
I've used Repository as the generic type because the ICache<T> interface constraints the type to Repository.
Now the problem: I've got a method to add a cache that looks like this
static void Add<TCache>(Repository repo)
where TCache : Repository, ICache<TCache>
{
ICache<TCache> newEntry = Activator.CreateInstance(typeof(TCache), repo) as ICache<TCache>;
Caches.Add(newEntry); // Error: Cannot convert from ICache<TCache> to ICache<Repository>
}
That confuses me. From my understanding this should work because I've added the constraint where TCache : Repository to the method, so adding an item of that type
to a list of ICache<Repository> should work. It's the same constraint.
What's the problem here?