Andrew
Andrew

Reputation: 5146

Add non-generic methods to generic classes

I'm using a unit of work / generic repository pattern almost identical to the example Microsoft provides, and it works great. However, the need has recently arisen for some methods that are only applicable to a particular type of repository.

For example, say I have two classes corresponding to database tables: People and Spaceships.

unitofwork.People is a Repository<Person> and unitofwork.Spaceships is a Repository<Spaceship>. While both repositories have the methods I defined in

public class Repository<TEntity> where TEntity : class, IEntity

what if I want some Person-specific methods to be available on unitofwork.People? Is this possible?

Upvotes: 0

Views: 237

Answers (1)

CodingIntrigue
CodingIntrigue

Reputation: 78545

You could make Repository<T> an abstract class. Then each entity must have their own implementations:

abstract class RepositoryBase<TEntity> where TEntity : class, IEntity {
    void Add(TEntity entity);
    ...
}

class PeopleRepository : RepositoryBase<Person> {
    string GetPersonName();
}

class SpaceshipRepository : RepositoryBase<Spaceship> {
    void Fly();
}

You'd then implement the classes as:

unitofwork.People = new PeopleRepository();
unitofwork.People.Add(new Person()); // Can access the base class
Console.WriteLine(unitofwork.People.GetPersonName()); // People-specific methods
unitofwork.Spaceships = new SpaceshipRepository();

If you want to be able to initialise an instance of the base repository, there is no need to mark it as abstract:

class Repository<TEntity> where TEntity : class, IEntity {
    void Add(TEntity entity);
}

class PeopleRepository : Repository<Person> {
    string GetPersonName();
}

If you want to stop the PeopleRepository from providing its own methods, then you can use the sealed modifier:

class Repository<TEntity> where TEntity : class, IEntity {
    sealed protected void Add(TEntity entity);
}

Upvotes: 2

Related Questions