🗡️
ConanJs
  • What is ConanJs?
  • Why ConanJs...
    • ... if coming from Redux
    • ... if using vanilla React
    • ... if learning React
    • ... if not using React
  • How to install/use ConanJs
  • About us / Github / Contact us
  • Demos
    • Demo Gallery
    • Conan State Demos
      • Hello World
      • Todos
        • Todos - Basic
        • Todos - Async
        • Todos - Optimistic
      • Github issues viewer
    • Conan Flow Demos
      • Authentication
  • CONAN DATA
    • General Concepts
    • Conan State
      • Actions & Reducers
        • Reducers
        • Actions
      • Creating State
      • Observing State
        • Live rendering
        • Connecting
      • Composing State
      • Scaling State
      • Orchestrating State
      • Life cycle
        • Async handling
        • Introspection
      • Testing state
    • Conan Flow
      • Creating Flows
      • Serialising Flows
      • Observing Flows
  • CONAN Runtime
  • Dependency Injection
    • General Concepts
    • Creating the Context
    • Using the Context
  • ASAPs
  • Logging
  • API
    • Main Classes
      • Conan
        • StateDef
      • ConanState
      • ConanFlow
        • UserFlowDef
        • UserStatusDef
        • Status
    • Conan State Classes
      • Thread
      • ConnectedState
      • MonitorInfo
      • MetaInfo
    • Dependency Injection
      • DiContextFactory
    • ASAPS
      • Asaps
      • Asap
Powered by GitBook
On this page
  • Introduction
  • Creating beans
  • Adding values to the context
  • Adding hints to the context
  • Functions/classes as values
  • Combining Hints and Values
  • Dynamic context

Was this helpful?

  1. Dependency Injection

Creating the Context

PreviousGeneral ConceptsNextUsing the Context

Last updated 4 years ago

Was this helpful?

Introduction

Let's now get hands on creating different through the context.

The principle is always the same: use DiContextFactory.createContext to pass the with their .

We will now show all the different use cases starting from the simple cases to the complex ones.

Creating beans

Adding values to the context

The simplest bean to create is a :

const diContext = DiContextFactory.createContext({
    baseUrl: 'localhost' // this is a value
});

Adding values let's you access them directly

console.log(diContext.baseUrl); //This will printout 'localhost'

Adding hints to the context

The real value of the dependency injection is to get it to create complex objects for you.

This is the case for , (functions or class definitions)

Parameterless hints

When you need to add hints, which class constructor or function are parameterless, you can do this by passing the class or the function reference directly.

class MyAmazingClass {
    saySomething (){ return 'something'}
}

const diContext = DiContextFactory.createContext({
    myAmazingObject: MyAmazingClass, // this is class hint
});
console.log(
    diContext.myAmazingObject.saySomething()
); //This will print 'something'

Internal dependencies

Now that we have seen the simplest case of parameterless hints, let's see what would happen if we needed to specify an internal dependency.

Let's also show something closer to a real world case, let's imagine that the strings to be used for MyAmazingClass could be configured from the outside as you might need to if your applications supports many locales.

class MyAmazingClass {
    constructor (somethingStr){
        this.somethingStr = somethingStr;
    }
    
    saySomething (){ return this.somethingStr}
}

const diContext = DiContextFactory.createContext({
    myAmazingObject: MyAmazingClass, // this is class hint
},{
    somethingStr: 'something'
);

Function hints

The same principle that applies to classes can also apply to functions.

Is your choice when hinting if you want to use a full fledge class or a function that returns something.

We can see this in the following example

function rollDice () {
    return Math.floor(Math.random() * 6) + 1  
}

const diContext = DiContextFactory.createContext({
    randomRoll: rollDice, // this is function hint
})

And also we can see how we can use function hints and internal dependencies.

function rollDice (maxValue) {
    return Math.floor(Math.random() * maxValue) + 1  
}

const diContext = DiContextFactory.createContext({
    randomRoll: rollDice, // this is function hint
}, {
    maxValue: 6
})

Functions/classes as values

Because functions and class are always assumed to be hints, you will find that it might now work as you expect if you need to have a dependency to be resolved to a function or a class...

For instance:

function sayHello (){
    return 'hello'
}
const diContext = DiContextFactory.createContext({
    sayHello
});

The bean definition in the example above 'sayHello' is considered to be a hint (is a function), so if you access it through the context, the actual result would be the string 'hello'

console.log(diContext.sayHello); //This will printout 'hello'
console.log(diContext.sayHello()); //This will throw an error

If you wanted the function to be used as a value, and not as a hint, you will have to wrap it into an additional function.

This will trick the framework in resolving it to your original function, for instance to receive as a bean the function sayHello, instead of its returning value:

function sayHello (){
    return 'hello'
}

const diContext = DiContextFactory.createContext({
    sayHello: ()=>sayHello
});

console.log(diContext.sayHello()); //This will print helllo

As of v1.0 we are hoping to provide with you with a simpler mechanism to pass functions and class as hints in one of our first next releases.

Combining Hints and Values

The real power from dependency injection is that it lets you combine any level of hints and/or values.

class StockService{
    constructor (stockEndpoint){
         this.stockEndpoint = stockEndpoint
    }
}

class Endpoint {
    constructor (baseUrl){
        this.baseUrl = baseUrl
    }
}

const diContext = DiContextFactory.createContext({
    stockService: StockService, // this is the hint to create a StockService
    stockEndpoint: Endpoint, // we need to populate the value for the baseUrl
},{
    baseUrl: 'localhost'
});

As you can see in the example above, we have:

  • stockEndpoint: A hint for the class Endpoint. Note that the constructor receives a parameter named 'baseUrl', this matches the aux bean definition, which means that it will be injected into the stockEndpoint bean.

  • stockService. A hint for the class StockService, the bean created in this context will receive injected through the constructor the stockEndpoint.

Dynamic context

A side effect of working with plain objects to store the context, is that as with as any other normal object, you can use functions to generate the context, or that you can change the context after it has been created.

You will see in the next section how this combined with the other features from dependency injection will let you for example write simpler integration tests.

We think that having a dynamic context is key to fully take advantage of the dependency injection

As of v1.0, we don't have any out of the box mechanism to help you create dynamic context, but we are hoping to change this in the near future.

baseUrl: An used to initialise an Endpoint

beans
bean names
bean definitions
value
hints
aux bean definition
Come on! Next section everything come together!