17

I am a big fan of DI/IOC. It is great for handling/abstracting away hard dependencies, and makes life a little easier.

However I have a small gripe with it, which I am not sure how to solve.

The basic idea in DI/IOC is that when an object is instantiated, all of its dependencies are pre-filled within the constructor.

However IMHO there are several types of parameters for constructors (especially when your objects are immutable).

  1. Dependencies (Objects required for your object to do work)
  2. Configuration (information about the environment required to do work)
  3. Parameters (Data that work is done on)

I find that IOC works well with dependencies. But I am still trying to work out the best way to deal with the other two. However, since the constructor is run meant to be run by the IOC container, it seems I need to place these items into the IOC container.

I'd like to know what strategies/patterns people employ and what advantages and disadvantages people have found.

NB. I am aware this is a highly subjective question, and have tried to make it a "good" subjective question as per SE guidelines.

  • By "Configuration" do you mean the dev-environment configuration (like Development or Production)? If so, I usually handle that as a traditional Dependency. – MetaFight Feb 10 '14 at 12:12
  • Best to construct with dependencies but default configuration so the object is well formed. Call additional methods to set configuration and other parameters. Doing too much in the ctor is a bad thing. – david.pfx Feb 10 '14 at 13:41
  • I am still trying to work out the best way to deal with the other two -- Pass them in as ordinary parameters to your object? – Robert Harvey Feb 10 '14 at 16:48
  • @RobertHarvey immutable objects? They make debugging much easier. – ArTs Feb 11 '14 at 1:22
9

Configuration (information about the environment required to do work)

Create a configuration class (to be picky: an interface + an implementation) which purpose is to provide the information about the environment. This makes the configuration in no way different from other objects required for your object to do work (point 1).

Parameters (Data that work is done on)

In an object oriented environment, primitive data types can be encapsulated in objects, so this also leads to point 1. But you will probably find this SO question interesting, it deals exactly with the situation of primitive parameters in a constructor, when using a DI container. In the given example, the design could be improved, which avoided the need for primitive types in the constructor completely.

1

What I do is a factory pattern for these cases.

I do not use the object itself as a dependency but create a factory object with a Get method that accepts parameters that can't be bound automatically by the container.

Ex.:

 interface IDependencyObject {
       ....
 }

 class DependencyObject {

      public DependencyObject(int primitive, IAnotherDependency anotherDependency) {
      ...
      }

 }

 class DependencyObjectFactory {

      private readonly IAnotherDependency anotherDependency;

      public DependencyObjectFactory(IAnotherDependency anotherDependency) {
           this.anotherDependency = anotherDependency;
      }

      public IDependencyObject Get(int primitive) {
           return new DependencyObject(primitive, anotherDependency);
      }
 }

 interface IDependencyObjectFactory {
       IDependencyObject Get(int primitive);
 }

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.