5

I'm a little bit confused around Constructor Injection pattern and rule Don’t call the container; it’ll call you.

Can somebody explain me (and maybe someone else) how real application should derive all DI advantage using Constructor Injection ? I give for that some simple and i think common example:

DomainObject
RepositoryObject
DaoObject

The relations is obvious (I think) - RepositoryObject need DaoObject,DomainObject need Repository.

Using Constructor Injection I assume that I can forget (in most cases) about NEW keyword, but when, where and how should I create new objects (mainly domain)? I must write factories for all classes? Should I refer to DI Container in that factory?

The best will be when somebody show me some real app example (please not Asp.Net MVC :) ) or sketch some project structure.

mgibas
  • 408
  • 4
  • 14
  • 2
    See this answer: http://stackoverflow.com/questions/6277771/what-is-a-composition-root-in-the-context-of-dependency-injection/6277806#6277806 – Mark Seemann Jul 04 '11 at 18:25
  • @Mark - Ok, i think I grasp that but I have some problems with creation of domain object. Lets assume that I have created controller object (Global.asax as root of app) and now I have some action (post), and have to create at this point, lets say - new Book, and Book need some dependency ofc (Repository or something) . So how to create that new object? Should I ALWAYS provide that dependency's to Controller object, although that some of them is used ONLY to create my "Book" object ? The same situation is with Repositorys (some of their method create new domain objects). – mgibas Jul 05 '11 at 05:58
  • 1
    http://stackoverflow.com/questions/4835046/why-not-use-an-ioc-container-to-resolve-dependencies-for-entities-business-object/4836790#4836790 – Mark Seemann Jul 05 '11 at 14:57

2 Answers2

1

I don't get your class relationship so here's a more obvious ;-) example:

class FooService
{
    IFooRepository FooRepository { get; set; }

    public Service(IFooRepository fooRepository)
    {
        this.FooRepository = fooRepository;
    }
}

class Controller
{
    IFooService FooService { get; set; }
    IBarService BarService { get; set; }

    public Controller(IFooService fooService, IBarService barService)
    {
        this.FooService = fooService;
        this.BarService = barService;
    }
}

As you've already said - there is no new FooRepository() nor new FooService() code anywhere.

Jakub Konecki
  • 45,581
  • 7
  • 87
  • 126
  • You need to use a container that has an MVC integration, ie. http://code.google.com/p/autofac/wiki/Mvc3Integration – Jakub Konecki Jul 05 '11 at 05:40
  • Thx, but I know how to use it in MVC to create controller, but what with the rest of objects (domain mainly) ? – mgibas Jul 05 '11 at 08:39
  • Domain object (nested objects) will be created automatically by the DI container based on your configuration. You have to configure your DI container (either through code or some config files) by telling it which class to instantiate for each constructor argument. In my example you will tell DI container to instantiate `FooService` every time it sees an argument of type `IFooService`, so when it creates a controller it knows what to pass as the argument. – Jakub Konecki Jul 05 '11 at 11:32
  • ok, but what about when You want to create new Domain object in e.g. in controller action (look at my comment on Mark answer/comment) – mgibas Jul 05 '11 at 12:32
  • In MVC you would assign your DI container to `DependencyResolver.Current` (see http://weblogs.asp.net/shijuvarghese/archive/2011/01/21/dependency-injection-in-asp-net-mvc-3-using-dependencyresolver-and-controlleractivator.aspx). You can use `DependencyResolver.Current` yourself to construct the objects - you will go through the DI container. – Jakub Konecki Jul 05 '11 at 15:41
1

The answers and Mark Seemann's link is enough but i want to add something. As a beginner to DI ( which i am) this question is always bugs me: "Ok there is no new but when and how my real objects are called and injected?". It took me for a while for me to understand and apply.

As you follow the answers and links you will see that. You should register your interfaces and classes in your applications Global.asax file for web application. For instance if you are using Ninject go to nuget and download Ninject.Web ( which is for webforms) and apply it like in this example http://azolotar.blog.com/2010/06/22/ninject-2-0-in-webforms/

Keypoint in the example.

  • Global.asax is inherited from NinjectHttpApplication ( which is in Ninject.Web.dll)
  • CreateKernel method is overridden this is where you create the kernel and tell your dependecy map to container
  • BasePage : this is for webforms so your interface in pages would be resolved if they are all derived from basepage.

I should add this, BasePage implementation is pretty easy ( here is the code on github) you probably already have an basepage so adding this line KernelContainer.Inject(this); to your base page's OnInit can solve the problem. One last remainder, if you are going to use anything in ascx you should override your ascx's OnInit so container can solve dependencies.

I know you said no MVC or web :)But the logic is the same

  • Set your depenceny map on start of application ( Main? for windows)
  • Since its not web no url no directly calling forms you will call it How to use Ninject in a Windows Forms application? as in this example. Dont know if you are using some patters MVP or MVVM but this can be a starting point

Damn this sounds not helpful answer but anyway , hope this helps.

Community
  • 1
  • 1
adt
  • 4,320
  • 5
  • 35
  • 54