2

I am using the repository pattern found in the answer to this SO question:

Advantage of creating a generic repository vs. specific repository for each object?

Namely, each repository inherits from an abstract base class that contains generic methods like add, delete, etc. and also implements a specific repository interface for any methods that are unique to that repository/entity.

ie.

public class CompanyRepository : Repository<Company>, ICompanyRepository {
...
}

In my business layer I am using Structure Map to get an instance of the repository, but I am unsure how to use it.

 // Structure Map initialisation
 ObjectFactory.Initialize(
 x =>
 {                    
      x.For<ICompanyRepository>().Use<CompanyRepository>();
 });

resolving an instance:

return ObjectFactory.GetInstance<ICompanyRepository>();

However the instance I get is an interface and not the whole repository implementation. I don't have access to the methods on the base class (Repository<Company>). What is the usual way to do this?

Community
  • 1
  • 1
dan
  • 5,664
  • 8
  • 45
  • 59

2 Answers2

2

The key here is to think of Repository<> solely as an implementation detail. You won't be accessing any methods on it directly; instead, you will expose all methods, including Insert and Delete, on the interface:

public interface ICustomerRepository
{
    // ...Customer-specific queries...

    void Insert(Customer customer);

    void Delete(Customer customer);
}

When you implement the interface in CustomerRepository, you simply have to pass the Insert and Delete calls through to the protected methods of Repository<> as discussed in the original question.

The StructureMap registration you state in the question is exactly what I would expect. The purpose of Repository<> then is to aid in the implementation of entity-specific interfaces. Keep in mind that the interfaces will always contain the repository's full public API and that should point you in the right direction.

Bryan Watts
  • 44,911
  • 16
  • 83
  • 88
  • Great -thanks for the clarification - I was missing the step of exposing the Repository<> methods on the interface. – dan Dec 01 '10 at 06:45
1

Why not

return ObjectFactory.GetInstance<Repository<Company>>;

? You will have to modify accordingly your ObjectFactory initialization:

// Structure Map initialisation
ObjectFactory.Initialize(
    x => {                    
      x.For<Repository<Company>>().Use<CompanyRepository>();
    });

EDIT
If you still want to get Repository<Company> also for ICompanyRepository, you need to declare a forwarding:

// Structure Map initialisation
ObjectFactory.Initialize(
    x => {                    
      x.For<Repository<Company>>().Use<CompanyRepository>();
      x.Forward<Repository<Company>, ICompanyRepository>();
    });
Simone
  • 11,655
  • 1
  • 30
  • 43
  • Then I don't get access to the methods defined in the interface. I really need to get a CompanyRepository however I don't know if this will negate the benefit of DI/IoC? – dan Nov 30 '10 at 10:15
  • Thanks for your feedback. How do I then get a CompanyRepository? return ObjectFactory.GetInstance>() and cast it to a CompanyRepository? Seems to work. – dan Nov 30 '10 at 10:40
  • You get it by `ObjectFactory.GetInstance>` **or** by `ObjectFactory.GetInstance`. – Simone Nov 30 '10 at 10:43
  • It works but that's not what I'd do. You really should need the interface or the abstract base class, not the concrete class! – Simone Nov 30 '10 at 10:48
  • I guess that's the crux of my question - how can this particular repository pattern (with an abstract class and an interface) properly use IoC? Perhaps it is a flaw in the pattern. Thanks for your time. – dan Nov 30 '10 at 10:53