2

I have a big View with about 7 dropdowns to diferents models... So, in my controller´s constructor I have 9 IRepository, like that :

public CrudController(IRepository<Class1> class1Rep, IRepository<Class2> class2Rep,  ... 
IRepository<Class9> class9Rep)
{
    this.class1Rep = class1Rep;
   ...
    this.class9Rep = class9Rep;
}

So, I can populate my ViewModel with all necessary data...

Is that the right way to do that? I´m using Ninject...

Thanks

Paul
  • 12,359
  • 20
  • 64
  • 101
  • 2
    You could check the UnitOfWork pattern. It will simplify your application. Look this as example http://msdn.microsoft.com/en-us/magazine/dd882510.aspx – vladislavn Oct 03 '13 at 18:47
  • @ВладиславНайденов - UnitOfWork and Repository are not mutually exclusive. Most implementations of repository also use UnitOfWork internally, so your answer doesn't really answer his question. – Erik Funkenbusch Oct 03 '13 at 19:40
  • You might like suggestions on this question [Strategy to refactor when too many dependencies injected into service or controller][1] [1]: http://stackoverflow.com/questions/6025482/strategy-to-refactor-when-too-many-dependencies-injected-into-service-or-control – ntombela Oct 03 '13 at 20:07
  • See these questions relating to over injection http://stackoverflow.com/questions/9136091/mvc-controller-with-multiple-select-lists/9141989#9141989, http://stackoverflow.com/questions/14511811/massive-controller-constructor-argument-list-when-using-di-in-mvc/14512226#14512226, http://stackoverflow.com/questions/2420193/how-to-avoid-dependency-injection-constructor-madness – GraemeMiller Oct 08 '13 at 19:48

3 Answers3

1

Instead of passing multiple repositories, you pass a single instance of a Unit of Work. The trick is to implement it correctly, here is one:

http://www.asp.net/mvc/tutorials/getting-started-with-ef-using-mvc/implementing-the-repository-and-unit-of-work-patterns-in-an-asp-net-mvc-application

(the UoW part starts somewhere at the end)

What is still missing there is that you have a uow interface and multiple implementations. For example, an Entity Framework unit of work has the content injected so that it can pass the context down to repositories. An inmemory unit of work can have other dependencies etc.

Ultimately, your IoC container just resolves the Unit of Work.

Wiktor Zychla
  • 47,367
  • 6
  • 74
  • 106
  • 1
    I would disagree with this, as the point of the repository is to abstract the implementation details like the UoW. Many Repository implementations even use the UoW inside to coordinate multiple statements across repositories. UoW and Repository have different purposes, and should not be used interchangeably. – Erik Funkenbusch Oct 03 '13 at 19:42
  • Your comment correctly recalls Fowler's definition. I am not sure where did this "wrapper for multiple repositories" idea come from and how it gained so much attention but I am one of those who like it. Is there another name for it perhaps? – Wiktor Zychla Oct 03 '13 at 20:10
1

One simple answer is to simply create a wrapper class that contains all your repositories, then you need only pass the wrapper class.

However, most purists would say that if you have that many repositories, you're probably violating the Single Responsibility Principle and should break out the functionality into other classes.

Erik Funkenbusch
  • 92,674
  • 28
  • 195
  • 291
1

Looks like a violation of SRP. Does each View Model require all repositories? Do some ViewModels just use a couple? Are you doing other complex work to create ViewModel? If so I would abstract the general concept of ViewModel construction and ideally use something like Automapper to remove any mappings.

We abstract the concept of populating the select lists and other complex work using an IModelEnricher<T> where T is a ViewModel. IModelEnricher<T> defines one method Enrich which takes an instance of the T ViewModel and returns an instance T. In the Enrich method do any clever work you need to do. If you need two repositories for a ViewModel then you are only injecting those into the constructor of your IModelEnricher<T>

We automatically use an IModelEnricher to enrich ViewModels returned from our Action results. We always also automap our domain model to the ViewModel in the same pipeline. Most Get controller actions are a single line of code as Automapper handles taking Domain Model to ViewModel and enricher does any additional stuff.

retrun AutoMappedView<AConcreteViewModel>(repository.Find(id))

If a class implemeting IModelEnricher is found for AConcreteViewModel it will be called and any work done e.g.

    public class AConcreteViewModelEnricher:IModelEnricher<AConcreteViewModel>{

    AConcreteViewModelEnricher(Repo1 repo1, Reop2 rep2){
........
}

    AConcreteViewModel Enrich(AConcreteViewModel model){
           //Do stuff with repo etc and 
            return model
    }
}

See my answer to your other question about drop downs.

Community
  • 1
  • 1
GraemeMiller
  • 11,973
  • 8
  • 57
  • 111