views:

135

answers:

2

In this post I talked about using a generic base class to enable me to create repository classes without duplicating loads of basic plumbing code.

Each Repository is accessed through an interface. In the code below, I will only show one of the methods for the sake of brevity:

Interface:

IQueryable<Suggestion> All { get; }

Generic base class

public IQueryable<T> All
    {
      get { return _unitOfWork.GetList<T>(); }
    }

Concrete class (implements the interface and extends the generic base class)

public IQueryable<Suggestion> All
    {
      get { return _unitOfWork.GetList<Suggestion>(); }
    }

I anticipated that I would be able to simply strip the method out of the concrete class, and the compiler would use the generic base class implementation instead and work out that was intended to satisfy the interface. But no!

When I strip the method out I get the old 'does not implement interface member' error.

If I can't do this, have my efforts to use a generic base class not been pointless? Or is there a way around this?

+6  A: 

Can you make the interface itself generic then implement a typed version in your concrete class?

public interface IRepository<T>
{
    List<T> All { get; }
}

public class Repository<T>
{
      public List<T> All 
      {
          get { return new List<T>(); }
      }
}

public class SuggestionRepository : Repository<Suggestion>, IRepository<Suggestion>
{ }

I'd still suggest using the generic interface since it will save you from repeating yourself, but this works too.

public interface ISuggestionRepository
{
    List<Suggestion> All { get; }
}

public class Repository<T>
{
      public List<T> All 
      {
          get { return new List<T>(); }
      }
}

public class SuggestionRepository : Repository<Suggestion>, ISuggestionRepository
{ }
Martin Harris
Although that would presumably work, I want to have separate interfaces for each repository class in order to configure dependency injection for each one.
David
They are separate interfaces since they have a different generic type. All DI frameworks I've used will allow you to inject these as different items.
Martin Harris
Oh okay, thanks for the heads up.
David
A: 

Use the virtual keyword and put your interface on your concrete implementation..

public interface IMyInterface<T>
{
    IQueryable<T> All { get; }
}

public abstract class MyBaseClass<T> : IMyInterface<T>
{
    public virtual IQueryable<T> All
    {
        get { return _unitOfWork.GetList<T>(); ; }
    }
}

public class MyClass : MyBaseClass<Suggestion>, IMyInterface<Suggestion>
{

}
Nix
It's usually best practise to write `public virtual`. The convention most popularly used is:<access specifier><override/virtual/abstract...><return-type><Method name> (<params>)
GenericTypeTea
Agreed. Sorry. Was trying to put together something quickly.
Nix