I'm currently struggling a bit to understand how I can use the dependency injection pattern outside of my controller classes.
Say for instance that I have the following controller:
public class TestController : Controller {
ILog logger;
public TestController(ILog log) {
logger = log;
}
public string TestMethod() {
businessLayer businessLayer = new businessLayer();
return businessLayer.DoSomethingAndLogIt();
}
}
I understand that in most cases it is not possible to use constructor injection outside of the controller-classes. So it would not be possible to directly use the ILog-implementation insdie the "businesslayer"-class.
One simple solution I could imagine is the following:
public class TestController : Controller {
ILog logger;
public TestController(ILog log) {
logger = log;
}
public string TestMethod() {
businessLayer businessLayer = new businessLayer(logger);
return businessLayer.DoSomethingAndLogIt();
}
}
So passing on the dependencies from the controller to the underlaying layers. But is this the best way? Are there better solutions to have my businessLayer-class access to the ILog-implementation?
Thx!
I understand that in most cases it is not possible to use constructor
injection outside of the controller-classes.
This is incorrect. You should use constructor injection for all your components (every class in your application that contains behavior).
Dependency injection is about injecting dependent services/components into consuming components. So this means that you should not new up the businesslayer class in your controler; you should inject it using the constructor. By newing up this dependency you are violating the Dependency Inversion Principle, which causes high coupling. This again makes your code harder to test and makes it harder to change the controller and makes it much harder to apply cross-cutting concerns (such as logging, audit trailing, transaction management, etc) to the system.
So it would not be possible to directly use the ILog-implementation
insdie the "businesslayer"-class.
Incorrect. The ILog implementation should be injected into the constructor of your businesslayer class.
Long story short, your controller should look like this:
public class TestController : Controller {
IBusinessLayer businessLayer;
public TestController(IBusinessLayer bl) {
this.businessLayer = bl;
}
public string TestMethod() {
return businessLayer.DoSomethingAndLogIt();
}
}
Since TestController doesn't seem to use ILog directly, it should not be injected into its constructor. ILog is an implementation detail of the business layer class and implementation details should not leak to the consumer (this would again be a violation of the Dependency Inversion Principle).
Related
I am going to use SimpleInjector in MVC.5 application with WebAPI.2
Some methods of MVC controllers will create objects of repositories for CRUD operations.
Common approach on the Internet is a using interface of repository in MVC controller, like:
public class DashboardController : Controller
{
private readonly IDashboardRepository _repository;
public DashboardController (IDashboardRepository repository) {
_repository = repository;
}
[HttpPost]
public JsonData GetInfo()
{
return _repository.GetInfo();
}
...
Similar approach is recommended for WebAPI
However I would not like to pass IDashboardRepository into constructor of controller because of such reasons: I am sure that I will never mock implementation of repository. I do not need separate public interface for repository (current code base has no these interfaces and I'll need to change a lot of files to add them).
My repositories look like:
public class DashboardFunc : BaseFunc
{
public DashboardFunc(IApplicationStateProvider sp) :
base (sp)
{
}
public DashBoardData GetInfo()
{
...
I would like to use such code in controllers of MVC:
public class DashboardController : Controller
{
public DashboardController () {
}
[HttpPost]
public JsonData GetInfo()
{
DashboardFunc dashBoard = Global.MvcContainer.GetInstance<DashboardFunc>();
return Common.ToJson(dashBoard.GetInfo());
}
The same approach I would like for WebAPI controllers. The only difference is
DashboardFunc dashBoard = Global.WebApiContainer.GetInstance();
Is my modification (not using interface of repository in controller) of standard approach OK? Are there any potential issues that can arise in future that can lead architecture change?
Thank you!
Prevent falling back on calling Global.MvcContainer.GetInstance or any other form of Service Location
anti-pattern. There are a lot of downsides to this, even if you don't want to test that code. Downsides of using this are (among others):
You lose the ability for the container to change the given implementation for you; it makes your application less flexible.
You lose the ability for the container to diagnose the complete object graph for you.
You lose the ability to verify the configuration during app start or using an integration test.
You lose the ability to spot all the class's dependencies just by looking at a single line of code (the constructor).
So even when you don't need that interface, I would advice to still use constructor injection and do the following:
public class DashboardController : Controller {
private readonly DashboardFunc dashboard;
public DashboardController(DashboardFunc dashboard) {
this.dashboard = dashboard;
}
[HttpPost]
public JsonData GetInfo() {
return Common.ToJson(this.dashBoard.GetInfo());
}
}
I've implemented my UnitOfWork so that it keeps references to all repositories.
public interface IUnitOfWork
{
void Commit();
void RollBack();
}
public interface IMyUnitOfWork : IUnitOfWork
{
IFooRepository Foos { get; }
IBarRepository Bars { get; }
// Other repositories ...
}
Note that the repositories implements a generic type of repository interface.
public interface IFooRepository : IRepository<Entities.Foo>
{
// FooRepository specific methods goes here.
}
public interface IRepository<T> : IRepository
where T : class
{
}
Now how can I inject these repository to my UnitOfWork. Of course I want them with a lazy loading behavior. For example:
public class ConcreteUnitOfWork : IMyUnitOfWork
{
private readonly IUnityContainer unityContainer;
private IFooRepository fooRepository;
public ConcreteUnitOfWork(IUnityContainer unityContainer)
{
this.repositoryFactory = repositoryFactory;
}
public IFooRepository Foos
{
get
{
return this.fooRepository ??
(this.fooRepository = unityContainer.Resolve<IFooRepository>());
}
}
}
I know passing the Unity container to the UnitOfWork is incorrect but what pattern would you offer to solve this issue?
You may mention that I shouldn't keep the repository references in the UnitOfWork but please suppose a service class which needs several repositories. With this design I can just pass the UnitOfWork as the constructor parameter (Constructor Injection) to the service class, but if I didn't keep the repository references in UnitOfWork, I would have to pass all needed repositories as constructor parameters and you know what it leads to.
-- UPDATE --
Please let me know if I'm absolutely wrong and I should never compose the repositories in UnitOfWork. Then please give me a solution about "Constructor Over-injection" here.
-- UPDATE2 --
It seems that composing (referencing to) the repositories from UnitOfWork breaks the Open/Closed principle as we need to change the UnitOfWork class when we add a new repository (add a new property).
If it's right then I should consider a refactoring. Would you please give me some ideas?
It seems as though the current design proposal mixes more than one responsibility into the IMyUnitOfWork interface. You say that this is because otherwise a service class might need to take each Repository independently. I'm assuming you mean something like this:
public MyService(
IUnitOfWork uow,
IFooRepository fooRepository,
IBarRepository barRepository)
This seems to me to be a much simpler and cleaner design.
But then what about Constructor Over-injection?
Well, there's that... but the thing is that this is exactly the same problem you now have with your ConcreteUnitOfWork implementation. You haven't solved the Constructor Over-injection smell at all - you've just moved it to another class.
Actually, by moving it to ConcreteUnitOfWork you've made it more difficult to deal with the situation. Because ConcreteUnitOfWork is a pure infrastructure class (or a support class, if you will) it doesn't have any business context, so it's really hard to suggest a way resolve the Constructor Over-injection smell here.
On the other hand, a given Service (or perhaps a Controller) would tend to be more specialized and have knowledge of the business context, so it wouldn't need every repository in order to do its job - or if it does, it probably attempts to do too much.
Such a specific business component can better be refactored to a Facade Service.
What is the best way to manage the context of Entity Framework when using MVC application?
I am using a Repository/Service pattern.
Edit
After looking through some of these questions: stackoverflow.com/users/587920/sam-striano, I am more confused then before. Some say use the context per repository, but wht if I want to use multiple repositories in one controller method?
And to follow good separation design, how do you use UnitOfWork in the MVC app with out making it dependent on EF? I want to be able to unit test my controllers, model, services, etc. using a mock context?
Use a Dependency Injector/Inversion of Control framework like:
Ninject
Autofac
StructureMap
Unity
Using an IoC container, you can tell it how to manage a single data context (most commonly, per request). When you set the data context to per request, the container will auto-magically give any class that needs a data context the same data context per request.
Here is a good article on setting up Ninject.
What your code will most likely end up looking like, assuming you're using a generic repository:
Ninject Module:
public class NinjectRegistrationModule : NinjectModule
{
public override void Load()
{
Bind<MyDataContext>().ToSelf().InRequestScope();
Bind(typeof(RepositoryImplementation<>)).ToSelf().InRequestScope();
}
}
Generic Repository:
public RepositoryImplementation<T> : IRepository<T> where T : class
{
MyDataContext _dataContext;
public RepositoryImplementation<T>(MyDataContext dataContext)
{
_dataContext = dataContext;
}
// bunch of methods that utilize _dataContext
}
Service Class:
public class MyServiceClass
{
IRepository<SomeEntity> _someEntityRepository;
public MyServiceClass(IRepository<SomeEntity> someEntityRepository)
{
_someEntityRepository = someEntityRepository;
}
// do stuff with _someEntityRepository = someEntityRepository;
}
Controller:
public class MyController
{
MyServiceClass _myServiceClass;
public MyController(MyServiceClass myServiceClass)
{
// Ninject will auto-magically give us a myServiceClass
// which will Ninject will inject a repository into MyServiceClass's constructor
_myServiceClass = myServiceClass;
}
public ActionResult MyAction()
{
// use _myServiceClass to do stuff
return View();
}
}
If your functionality is straight forward, then you should create a new ObjectContext in each Repository. They are cheap to instantiate.
If this creates a conflict, you can use a Unit of Work pattern as was suggested in the comment.
I would advise that you be extremely cautious when integrating an ObjectContext or DataContext with a DI container. Many do not use the appropriate scope for their life cycle by default.
If you don't know what I'm talking about either go through the tutorial and try to add dependency Injection yourself or try your luck with my explanation of the problem.
Note: This problem isn't within the scope of the original tutorial on ASP.NET. The tutorial only suggests that the patterns used are dependency injection friendly.
The problem is basically that there is a dependency loop between the Controller, the ModelStateWrapper and the ContactManagerService.
The ContactController constuctor takes an IContactManagerService.
The ContactManagerService constructor takes an IContactManagerRepository (not important) and an IValidationDictionary (which ModelStateWrapper implements).
The ModelStateWrapper constructor takes a ModelStateDictionary (which is a property called "ModelState" on the controller).
So the dependency cycle goes like this: Controller > Service > ModelStateWrapper > Controller
If you try to add dependency injection to this, it will fail. So my question is; what should I do about it? Others have posted this question, but the answers are few, different, and all seem kinda "hack-ish".
My current solution is to remove the IModelStateWrapper from the IService constructor and add an Initialize method instead like this:
public class ContactController : Controller
{
private readonly IContactService _contactService;
public ContactController(IContactService contactService)
{
_contactService = contactService;
contactService.Initialize(new ModelStateWrapper(ModelState));
}
//Class implementation...
}
public class ContactService : IContactService
{
private IValidationDictionary _validationDictionary;
private readonly IContactRepository _contactRepository;
public ContactService(IContactRepository contactRepository)
{
_contactRepository = contactRepository;
}
private void Initialize(IValidationDictionary validationDictionary)
{
if(validationDictionary == null)
throw new ArgumentNullException("validationDictionary");
_validationDictionary = validationDictionary;
}
//Class implementation...
}
public class ModelStateWrapper : IValidationDictionary
{
private readonly ModelStateDictionary _modelState;
public ModelStateWrapper(ModelStateDictionary modelState)
{
_modelState = modelState;
}
//Class implementation...
}
With this construct I can configure my unity container like this:
public static void ConfigureUnityContainer()
{
IUnityContainer container = new UnityContainer();
// Registrations
container.RegisterTypeInHttpRequestLifetime<IContactRepository, EntityContactRepository>();
container.RegisterTypeInHttpRequestLifetime<IContactService, ContactService>();
ControllerBuilder.Current.SetControllerFactory(new UnityControllerFactory(container));
}
Unfortunately this means that the "Initialize" method on the service has to be called manually by the controller constructor. Is there a better way? Maybe where I somehow include the IValidationDictionary in my unity configuration? Should I switch to another DI container? Am I missing something?
As a general consideration, circular dependencies indicate a design flaw - I think I can safely say this since you are not the original author of the code :)
I wouldn't consider an Initialize method a good solution. Unless you are dealing with an add-in scenario (which you aren't), Method Injection is not the right solution. You have almost already figured that out, since you find it unsatisfactory that you need to manually invoke it because your DI Container can't.
Unless I am entirely mistaken, the ContactController doesn't need the IValidationDictionary instance before its Action methods are being invoked?
If this is true, the easiest solution would probably be to define an IValidationDictionaryFactory interface and make the ContactController constructor take an instance of this interface.
This interface could be defined like this:
public interface IValidationDictionaryFactory
{
IValidationDictionary Create(Controller controller);
}
Any Action method on the controller that needs an IValidationDictionary instance can then invoke the Create method to get the instance.
The default implementation would look something like this:
public class DefaultValidationDictionaryFactory : IValidationDictionaryFactory
{
public IValidationDictionary Create(Controller controller)
{
return controller.ModelState;
}
}
How about slightly changing/improving the design to something like this: http://forums.asp.net/t/1486130.aspx
Each controller has a virtual method Initialize to do stuff like that.
I think there is no better way because the IValidationDictionary is an abstraction layer between you current request/controller/modelstate and the IContactService. Injecting controllers modelstate into the service and then injecting the service into the controller is simply impossible using constructor injection. One has to be first.
May be there is a way using property injection? But I think this will be complicated too.
I'm starting to get into Unit Testing, Dependancy Injection and all that jazz while constructing my latest ASP.NET MVC project.
I'm to the point now where I would like to Unit Test my Controllers and I'm having difficulty figuring out how to appropriately do this without an IoC container.
Take for example a simple controller:
public class QuestionsController : ControllerBase
{
private IQuestionsRepository _repository = new SqlQuestionsRepository();
// ... Continue with various controller actions
}
This class is not very unit testable because of its direct instantiation of SqlQuestionsRepository. So, lets go down the Dependancy Injection route and do:
public class QuestionsController : ControllerBase
{
private IQuestionsRepository _repository;
public QuestionsController(IQuestionsRepository repository)
{
_repository = repository;
}
}
This seems better. I can now easily write unit tests with a mock IQuestionsRepository. However, what is going to instantiate the controller now? Somewhere further up the call chain SqlQuestionRepository is going to have to be instantiated. It seems as through I've simply shifted the problem elsewhere, not gotten rid of it.
Now, I know this is a good example of where an IoC container can help you by wiring up the Controllers dependancies for me while at the same time keeping my controller easily unit testable.
My question is, how is one suppose to do unit testing on things of this nature without an IoC container?
Note: I'm not opposed to IoC containers, and I'll likely go down that road soon. However, I'm curious what the alternative is for people who don't use them.
Isn't it possible to keep the direct instantiation of the field and also provide the setter? In this case you'd only be calling the setter during unit testing. Something like this:
public class QuestionsController : ControllerBase
{
private IQuestionsRepository _repository = new SqlQuestionsRepository();
// Really only called during unit testing...
public QuestionsController(IQuestionsRepository repository)
{
_repository = repository;
}
}
I'm not too familiar with .NET but as a side note in Java this is a common way to refactor existing code to improve the testability. I.E., if you have classes that are already in use and need to modify them so as to improve code coverage without breaking existing functionality.
Our team has done this before, and usually we set the visibility of the setter to package-private and keep the package of the test class the same so that it can call the setter.
You could have a default constructor with your controller that will have some sort of default behavior.
Something like...
public QuestionsController()
: this(new QuestionsRepository())
{
}
That way by default when the controller factory is creating a new instance of the controller it will use the default constructor's behavior. Then in your unit tests you could use a mocking framework to pass in a mock into the other constructor.
One options is to use fakes.
public class FakeQuestionsRepository : IQuestionsRepository {
public FakeQuestionsRepository() { } //simple constructor
//implement the interface, without going to the database
}
[TestFixture] public class QuestionsControllerTest {
[Test] public void should_be_able_to_instantiate_the_controller() {
//setup the scenario
var repository = new FakeQuestionsRepository();
var controller = new QuestionsController(repository);
//assert some things on the controller
}
}
Another options is to use mocks and a mocking framework, which can auto-generate these mocks on the fly.
[TestFixture] public class QuestionsControllerTest {
[Test] public void should_be_able_to_instantiate_the_controller() {
//setup the scenario
var repositoryMock = new Moq.Mock<IQuestionsRepository>();
repositoryMock
.SetupGet(o => o.FirstQuestion)
.Returns(new Question { X = 10 });
//repositoryMock.Object is of type IQuestionsRepository:
var controller = new QuestionsController(repositoryMock.Object);
//assert some things on the controller
}
}
Regarding where all the objects get constructed. In a unit test, you only set up a minimal set of objects: a real object which is under test, and some faked or mocked dependencies which the real object under test requires. For example, the real object under test is an instance of QuestionsController - it has a dependency on IQuestionsRepository, so we give it either a fake IQuestionsRepository like in the first example or a mock IQuestionsRepository like in the second example.
In the real system, however, you set up the whole of the container at the very top level of the software. In a Web application, for example, you set up the container, wiring up all of the interfaces and the implementing classes, in GlobalApplication.Application_Start.
I'm expanding on Peter's answer a bit.
In applications with a lot of entity types, it is not uncommon for a controller to require references to multiple repositories, services, whatever. I find it tedious to manually pass all those dependencies in my test code (especially since a given test may only involve one or two of them). In those scenarios, I prefer setter-injection style IOC over constructor injection. The pattern I use it this:
public class QuestionsController : ControllerBase
{
private IQuestionsRepository Repository
{
get { return _repo ?? (_repo = IoC.GetInstance<IQuestionsRepository>()); }
set { _repo = value; }
}
private IQuestionsRepository _repo;
// Don't need anything fancy in the ctor
public QuestionsController()
{
}
}
Replace IoC.GetInstance<> with whatever syntax your particular IOC framework uses.
In production use nothing will invoke the property setter, so the first time the getter is called the controller will call out to your IOC framework, get an instance, and store it.
In test, you just need to call the setter prior to invoking any controller methods:
var controller = new QuestionsController {
Repository = MakeANewMockHoweverYouNormallyDo(...);
}
The benefits of this approach, IMHO:
Still takes advantage of IOC in production.
Easier to manually construct your controllers during testing. You only need to initialize the dependencies your test will actually use.
Possible to create test-specific IOC configurations, if you don't want to manually configure common dependencies.