views:

336

answers:

3

Right now I'm trying to figure out a way to do things smarter, and in the course of doing so all i've managed to do is use a full bottle of excedrin in a single day.

Assume i have an interface called IRepository like so.

 public interface IRepository<T>
 {
    T Get(int id);
    void Add(T value);
    void Update(T value);
    void Delete(T value);
    ...
 }

And assume i have an implementation like

public class NHibernateRepository<T>
{
    ...
}

Now, all is fine and good, i can do all my basic operations against the repository to support all CRUD functionality, but i may want specialized operations, so assume i have an interface like this:

public interface IUserRepository : IRepository<User>
{
     IList<User> GetUsersByRole(Role role);
}

And an implementation like such:

public class UserRepository : NHibernateRepository<User>, IUserRepository
{
    ....
}

Ok, so that is the basic setup, now there's one more thing that i want to do. I want to have logging and transaction and things like that all transparently. So what i would like to do is use a dependency injection framework like Castle Windsor or StructureMap so that when i ask for IRepository, i'll get it wrapped by a LoggingRepository and a TransactionRepository, both of which implement IRepository.

So, what i want to do is something like this:

IUserRepository repository = container.Resolve< IUserRepository>();

and have it return a user repository that's wrapped in the Logging and Transaction decorators, but i can't think of a way that this will ever work. The only way i can think of getting this to work is by implementing UserRepository like such:

public class UserRepository : DecoratorRepository<T>, IUserRepository
{
    protected IRepository<T> Repository { get; set; }

    public UserRepository(IRepository<T> innerRepository)
    {
        Repository = innerRepository;
    }
}

This would mean that we would use Dependancy Injection to create a decorated repository and pass that into the constructor of the UserRepository and then use that as the repository in which we run operations against. This would work, but i still don't think it's ideal.

So, my question is, am I right in that this is the only way to do this, or am I not understanding this correctly or just missing something all together. Also, if you have run up against this problem before, how did you solve this problem?

A: 

Couldn't you have a LoggingRepository abstract base class that would handle logging for your different Get, Add, Update, Delete, make them virtual and then inherit from them?

I'm not sure though what problem you are trying to solve though as I would think you may have tried this? You could wrap in transactions as well, though most likely you'd want to do that in your NHibernateRepository.

rball
A: 

This blog looks like a solution to your problem. It's basically the same design except instead of having a protected IRepository you make it private readonly.

scottm
+2  A: 

If you are going to use decorators that sounds about right. Each decorator would have a constructor with an argument of IRepository and call the logging or transaction code around calls to the inner repository that it is decorating.

As an alternative you might consider, but that I have very little experience with is Aspect Oriented Programming. In that scenario you apply attributes to your classes that indicate what logging or transaction methods you want to use. At some point those methods get weaved into your code, this can be done as either as an extra compile step, or in the case of the SpringFramework.net at time of injection.

Jeremy Wilde