Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dependency injection with multiple repositories

I have a wcf service and on the client i have:

var service = new ServiceReference1.CACSServiceClient()

The actual service code is:

public CACSService() : this(new UserRepository(), new BusinessRepository()) { }

public CACSService(IUserRepository Repository, IBusinessRepository businessRepository)
{
     _IRepository = Repository;
     _IBusinessRepository = businessRepository;
}

So, all this works fine, but i don't like how i am newing up all the repositories at the same time because the client code might not need to new up the UserRepository and only interested in newing up the BusinessRepository. So, is there a way to pass in something to this code:
var service = new ServiceReference1.CACSServiceClient()
to tell it which repository to new up based on the code that is calling the service or any other advice i need to go about when designing the repositories for my entity framework. Thankx

like image 932
user282807 Avatar asked Feb 27 '10 19:02

user282807


1 Answers

The beauty of pure DI is that you shouldn't worry about the lifetimes of your dependencies, because these are managed for you by whoever supply them (a DI Container, or some other code you wrote yourself).

(As an aside, you should get rid of your current Bastard Injection constructors. Throw away the parameterless constructor and keep the one that explicitly advertises its dependencies.)

Keep your constructor like this, and use _IRepository and _IBusinessRepository as needed:

public CACSService(IUserRepository Repository, IBusinessRepository businessRepository) 
{ 
    _IRepository = Repository; 
    _IBusinessRepository = businessRepository; 
} 

If you worry that one of these repositories are not going to be needed at run-time, you can inject a lazy-loading implementation of, say, IUserRepsository instead of the real one you originally had in mind.

Let's assume that IUserRepository looks like this:

public interface IUserRepository
{
    IUser SelectUser(int userId);
}

You can now implement a lazy-loading implementation like this:

public class LazyUserRepository : IUserRepository
{
    private IUserRepository uRep;

    public IUser SelectUser(int userId)
    {
        if (this.uRep == null)
        {
            this.uRep = new UserRepository();
        }
        return this.uRep.SelectUser(userId);
    }
}

When you create CACService, you can do so by injecting LazyUserRepository into it, which ensures that the real UserRepository is only going to be initialized if it's needed.

The beauty of this approach is that you don't have to do this until you need it. Often, this really won't be necessary so it's nice to be able to defer such optimizations until they are actually necessary.

I first described the technique of Lazy Dependencies here and here.

like image 128
Mark Seemann Avatar answered Sep 29 '22 16:09

Mark Seemann