views:

390

answers:

4

Hi! 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

A: 

Instead of instantiating ("newing up") the repositories on construction, you could lazy load them in their properties. This would allow you to keep your second constructor, but have your first constructor do nothing.

The user could then assign these, as needed, otherwise.

For example:

public class CACSService
{
    public CACSService() {}

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

    private IUserRepository _IRepository;
    public IUserRepository Repository
    {
        get {
             if (this._IRepository == null)
                  this._IRepository = new UserRepository();
             return this._IRepository;
        }
    }

   // Add same for IBusinessRepository
}
Reed Copsey
+1  A: 

Do your repositories have object-level state? Probably not, so create them as singletons and have a DI container provide them to CACService.

Otherwise, are they actually expensive to create? If not, creating a new one per request has negligible cost compared to the RPC and database operations.

Using the Ninject dependency injection container, your CACService might look like the following. Other DI containers have equally succinct mechanisms of doing this.

public class CACSService
{
    public CACService
    {
        // need to do this since WCF creates us
        KernelContainer.Inject( this );
    }

    [Inject]
    public IUserRepository Repository
    { set; get; }

    [Inject]
    public IBusinessRepository BusinessRepository
    { set; get; }
}

And during your application startup, you would tell Ninject about these types.

Bind<IUserRepository>().To<UserRepository>().InSingletonScope();
Bind<IBusinessRepository>().To<BusinessRepository>().InSingletonScope();
Lachlan Roche
There's no need to resort to Singletons and default constructors. WCF is perfectly able to support **Constructor Injection**.
Mark Seemann
This implementation sounds cool, i will give it a shot and also try what Mark Seeman said about lazy loading the repository.
A: 

Preface: This is a general guide to dependency inversion. If you need the default constructor to do the work (e.g. if it is new'ed up by reflection or something else), then it'll be harder to do this cleanly.

If you want to make your application configurable, it means being able to vary how your object graph is constructed. In really simple terms, if you want to vary an implementation of something (e.g. sometimes you want an instance of UserRepository, other times you want an instance of MemoryUserRepository), then the type that uses the implementation (CACService in this case) should not be charged with newing it up. Each use of new binds you to a specific implementation. Misko has written some nice articles about this point.

The dependency inversion principle is often called "parametrise from above", as each concrete type receives its (already instantiated) dependencies from the caller.

To put this into practice, move the object creation code out of the CACService's parameterless constructor and put it in a factory, instead.

You can then choose to wire up things differently based on things like:

  • reading in a configuration file
  • passing in arguments to the factory
  • creating a different type of factory

Separating types into two categories (types that create things and types that do things) is a powerful technique.

E.g. here's one relatively simple way of doing it using a factory interface -- we simply new up whichever factory is appropriate for our needs and call its Create method. We use a Dependency Injection container (Autofac) to do this stuff at work, but it may be overkill for your needs.

public interface ICACServiceFactory
{
    CACService Create();
}

// A factory responsible for creating a 'real' version
public class RemoteCACServiceFactory : ICACServiceFactory
{
    public CACService Create()
    {
         return new CACService(new UserRepository(), new BusinessRepository());
    }        
}

// Returns a service configuration for local runs & unit testing
public class LocalCACServiceFactory : ICACServiceFactory
{
    public CACService Create()
    {
         return new CACService(
               new MemoryUserRepository(), 
               new MemoryBusinessRepository());
    }     
}
Mark Simpson
+6  A: 

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.

Mark Seemann
agree. Don't constraint yourself to default ctor because that's what WCF suggests. use IInstanceProvider to build your service instance.
Krzysztof Koźmic
Thankx Mark for the response. I might have 10 or 20 repositories for my domain classes, do i have to implement lazy loading for each? that would be a lot of code.
Well, one of my main points is that you may not have to do this at all. Consider carefully whether this could be a premature optimization or not. As one example, if you use LINQ to SQL or LINQ to Entities, you might very well end up implementing all your repositories based on the same context, and in such a case, the overhead of creating several repository instances may be negligible.
Mark Seemann
However, if you can measure the performance of your service and can verify that the overhead of creating each repository is significant, you will have to wrap each in a lazy version. Chances are, though, that you can write a reusable generic implementation so that you only need to write a single implementation, but that depends on how different from each other each of your repositories are. If you are using a DI Container, many of them offer interception capabilities so that you could centrally define this behavior for all repositories.
Mark Seemann
yeah, right now i have a context instanciated in each repository that's why i was worried about all this cos i dont wanna instanciated a bunch of context objects. But I just thought of an idea that might make things simpler.in the CACSServise I am just gonna new up SuperRepository, in the Supper repository have only 1 context for all child repositories and this will take care of the context being instanciated in all repositories. Then Add an interface called ISuperRepository where i declare the child repositories and in the service code i can just do SuperRepository.UserRepository.GetUser()
public IUserRepository UserRepository { get { IUserRepository _IUserRepository = new UserRepository(); return _IUserRepository; } } this is how the userrepository would look like inside the SuperRepository class So only the repositories requested by the caller would get new up.
Best practice for L2S and L2E is to have a single, shared context, so you would be better off injecting a context into each Repository. This also means that you most likely don't need to worry about Lazy Dependencies.
Mark Seemann
Thankx Mark. I will post the code after i get it finished and hope i get some feedback from you if my code looks right.