Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I make a WireBox injected dependency available to a constructor method?

In this example, I have a model object called test.cfc which has a dependency testService.cfc.

test has WireBox inject testService through a property declaration. The object looks like this:

component {

     property name="testService" inject="testService";

     /**
     *  Constructor
     */
     function init() {

         // do something in the test service
         testService.doSomething();

         return this;

     }

 }

For reference, testService has a single method called doSomething() which dumps out some text:

component
     singleton
{

     /**
     *  Constructor
     */
     function init() {

         return this;

     }


     /**
     *  Do Something
     */
     function doSomething() {

         writeDump( "something" );

     }

 }

The problem is, WireBox doesn't seem to inject testService until after the constructor init() method fires. So, if I run this in my handler:

prc.test = wirebox.getInstance(
     name = "test"
);

I get the following error message: Error building: test -> Variable TESTSERVICE is undefined.. DSL: , Path: models.test

Just for sanity sake, if I modify test so that testService gets referenced after the object is constructed, everything works fine. The problem seems to be isolated to constructor methods.

How can I make sure my dependencies can be referenced in my object constructor methods? Thanks for your assistance!

like image 764
Dave L Avatar asked Nov 08 '18 18:11

Dave L


People also ask

How does constructor dependency injection work?

When a class requires an instance of a Dependency, you can supply that Dependency through the class's constructor, enabling it to store the reference for future use. Constructor Injection is the act of statically defining the list of required Dependencies by specifying them as parameters to the class's constructor.

What is @inject in constructor?

Constructor Injection is the most common form of Dependency Injection. Constructor Injection is the act of statically defining the list of required dependencies by specifying them as parameters to the class's constructor.

What is constructor dependency injection in C#?

Constructor Injection Dependency Injection is done by supplying the DEPENDENCY through the class's constructor when creating the instance of that class. The injected component can be used anywhere within the class. Recommended to use when the injected dependency, you are using across the class methods.

How can I get dependency injection?

Types of Dependency Injection The injector class injects dependencies broadly in three ways: through a constructor, through a property, or through a method. Constructor Injection: In the constructor injection, the injector supplies the service (dependency) through the client class constructor.


1 Answers

Due to the order of construction, you can't use property or setter injections in the init() method. Instead, you can access them in the onDIComplete() method. I realized the WireBox docs only had a passing reference to this, so I have added this excerpt:

https://wirebox.ortusbooks.com/usage/injection-dsl/id-model-empty-namespace#cfc-instantiation-order

CFC Building happens in this order.

  1. Component is instantiated with createObject()
  2. CF automatically runs the pseudo constructor (any code outside the a method declaration)
  3. The init() method is called (if it exists), passing any constructor args
  4. Property (mixin) and setting injection happens
  5. The onDIComplete() method is called (if it exists)

So the proper version of your CFC would be as follows:

component {

     property name="testService" inject="testService";

     /**
     *  Constructor
     */
     function init() {
         return this;
     }

     /**
     *  Called after property and setter injections are processed
     */
     function onDIComplete() {
         // do something in the test service
         testService.doSomething();
     }

 }

Note, it would also be acceptable to switch to constructor injection, but my personal preference is property injection due to the reduced boilerplate of needing to receive the argument and persist it locally.

https://wirebox.ortusbooks.com/usage/wirebox-injector/injection-idioms

like image 111
Brad Wood Avatar answered Oct 07 '22 00:10

Brad Wood