EDIT
It seems to me you basically have these options to reduce constructor dependency count here:
- Split the controller
- Add layer in front of the two interfaces
- Switch to property injection
- Service locator
#3 and #4 are included for good measure, but they obviously don't actually decrease the dependency count, they only hide them from the constructor. They also have several disadvantages, and I consider service locator especially evil most of the time.
For #1, if you feel your constructor is actually doing two+ jobs, and there is a clean separation where you could split, I would do so. I assume from your responses that you have already considered this, however, and don't want to do this.
That leaves #2 - adding another layer. In this case that would be introducing a factory interface for that particular view model. Naively, I'll name this ICreateTestplanViewModelFactory, but you can name it something more sensical for your app if you wish. A single method on it would construct a CreateTestplanViewModel.
This makes the fact that the data for this view is coming from 2 sources merely an implementation detail. You would wire up an implementation which takes IReleaseDataProvider and ITemplateDataProvider as constructor dependencies.
This is along the lines of what I was suggesting:
public interface IProvideTestPlanSetupModel
{
CreateTestplanViewModel GetModel();
}
public class TestPlanSetupProvider : IProvideTestPlanSetupModel
{
private readonly IReleaseDataProvider _releaseDataProvider;
private readonly ITemplateDataProvider _templateDataProvider;
public TestPlanSetupProvider(IReleaseDataProvider releaseDataProvider, ITemplateDataProvider templateDataProvider)
{
_releaseDataProvider = releaseDataProvider;
_templateDataProvider = templateDataProvider;
}
public CreateTestplanViewModel GetModel()
{
var releases = _releaseDataProvider.GetReleases();
var templates = _templateDataProvider.GetTemplates();
return new CreateTestplanViewModel(releases, templates);
}
}
public class TestPlanController : Controller
{
private readonly IProvideTestPlanSetupModel _testPlanSetupProvider;
public TestPlanController(IProvideTestPlanSetupModel testPlanSetupProvider)
{
_testPlanSetupProvider = testPlanSetupProvider;
}
[HttpGet]
public ActionResult Create()
{
var createTestplanViewModel = _testPlanSetupProvider.GetModel();
return PartialView(createTestplanViewModel);
}
}
If you don't like constructing a view model anywhere outside the controller, the interface could provide an intermediate object with the same properties that you would copy to the view model. But that is silly, as this combination of data is only relevant for that particular view, which is precisely what the view model is supposed to represent.
On a side note, it seems you are running into pretty common annoyances doing read/write through the same model. Since these issues bother you so, you might investigate CQRS, which perhaps would make you feel less dirty about talking to the database directly for these types of queries and would help you get around the layering labyrinth we all enjoy so much. It seems promising, though I have not yet had the pleasure of test driving it in a production application.