Domanda Ho bisogno di un'iniezione di dipendenza in NodeJS, o come affrontare ...?


Attualmente sto creando alcuni progetti sperimentali con nodejs. Ho programmato molte applicazioni web Java EE con Spring e ho apprezzato la facilità di inserimento delle dipendenze.

Ora sono curioso: come faccio a fare un'iniezione di dipendenza con il nodo? Oppure: ne ho addirittura bisogno? Esiste un concetto di sostituzione, perché lo stile di programmazione è diverso?

Sto parlando di cose semplici, come la condivisione di un oggetto di connessione al database, finora, ma non ho trovato una soluzione che mi soddisfi.


166
2018-02-12 17:19


origine


risposte:


In breve, non è necessario un contenitore per le iniezioni di dipendenza o un localizzatore di servizi come in C # / Java. Dal momento che Node.js, sfrutta il module pattern, non è necessario eseguire la costruzione o l'iniezione di proprietà. Anche se puoi ancora.

La cosa bella di JS è che puoi modificare praticamente qualsiasi cosa per ottenere ciò che desideri. Questo è utile quando si tratta di test.

Guarda il mio esempio molto zoppo inventato.

MyClass.js:

var fs = require('fs');

MyClass.prototype.errorFileExists = function(dir) {
    var dirsOrFiles = fs.readdirSync(dir);
    for (var d in dirsOrFiles) {
        if (d === 'error.txt') return true;
    }
    return false;
};

MyClass.test.js:

describe('MyClass', function(){
    it('should return an error if error.txt is found in the directory', function(done){
        var mc = new MyClass();
        assert(mc.errorFileExists('/tmp/mydir')); //true
    });
});

Nota come MyClass dipende dal fs modulo? Come menzionato @ShatyemShekhar, puoi effettivamente fare l'iniezione di proprietà o costruttore come in altre lingue. Ma non è necessario in Javascript.

In questo caso, puoi fare due cose.

Puoi mozzare il fs.readdirSync metodo o è possibile restituire un modulo completamente diverso quando si chiama require.

Metodo 1:

var oldmethod = fs.readdirSync;
fs.readdirSync = function(dir) { 
    return ['somefile.txt', 'error.txt', 'anotherfile.txt']; 
};

*** PERFORM TEST ***
*** RESTORE METHOD AFTER TEST ****
fs.readddirSync = oldmethod;

Metodo 2:

var oldrequire = require
require = function(module) {
    if (module === 'fs') {
        return {
            readdirSync: function(dir) { 
                return ['somefile.txt', 'error.txt', 'anotherfile.txt']; 
            };
        };
    } else
        return oldrequire(module);

}

La chiave è sfruttare la potenza di Node.js e Javascript. Nota, sono un ragazzo di CoffeeScript, quindi la mia sintassi JS potrebbe non essere corretta da qualche parte. Inoltre, non sto dicendo che questo è il modo migliore, ma è un modo. I guru di Javascript potrebbero essere in grado di interagire con altre soluzioni.

Aggiornare:

Questo dovrebbe indirizzare la tua domanda specifica riguardo le connessioni al database. Creerei un modulo separato per il tuo incapsulare la tua logica di connessione al database. Qualcosa come questo:

MyDbConnection.js: (assicurati di scegliere un nome migliore)

var db = require('whichever_db_vendor_i_use');

module.exports.fetchConnection() = function() {
    //logic to test connection

    //do I want to connection pool?

    //do I need only one connection throughout the lifecyle of my application?

    return db.createConnection(port, host, databasename); //<--- values typically from a config file    
}

Quindi, qualsiasi modulo che necessita di una connessione al database includerebbe solo il tuo MyDbConnection modulo.

SuperCoolWebApp.js:

var dbCon = require('./lib/mydbconnection'); //wherever the file is stored

//now do something with the connection
var connection = dbCon.fetchConnection(); //mydbconnection.js is responsible for pooling, reusing, whatever your app use case is

//come TEST time of SuperCoolWebApp, you can set the require or return whatever you want, or, like I said, use an actual connection to a TEST database. 

Non seguire questo esempio testualmente. È un esempio zoppo nel cercare di comunicare che tu usi il module modello per gestire le dipendenze. Spero che questo aiuti un po 'di più.


84
2018-02-13 02:48



require è il modo di gestire le dipendenze in Node.js e sicuramente è intuitivo ed efficace, ma ha anche i suoi limiti.

Il mio consiglio è di dare un'occhiata ad alcuni contenitori di Dependency Injection disponibili oggi per Node.js per avere un'idea su quali sono i loro pro / contro. Alcuni di loro sono:

Solo per citarne alcuni.

Ora la vera domanda è, cosa si può ottenere con un contenitore DI Node.js, rispetto a un semplice require?

Professionisti:

  • testabilità migliore: i moduli accettano le loro dipendenze come input
  • Inversion of Control: decidi come collegare i tuoi moduli senza toccare il codice principale della tua applicazione.
  • un algoritmo personalizzabile per la risoluzione dei moduli: le dipendenze hanno identificatori "virtuali", di solito non sono legati a un percorso sul filesystem.
  • Migliore estensibilità: abilitata da IoC e identificatori "virtuali".
  • Altre cose fantastiche possibili:
    • Inizializzazione asincrona
    • Gestione del ciclo di vita del modulo
    • Estensibilità del contenitore DI stesso
    • Può facilmente implementare astrazioni di livello superiore (ad esempio AOP)

Contro:

  • Diverso dall'esperienza Node.js: non usare require sembra decisamente che tu stia deviando dal modo di pensare del Nodo.
  • La relazione tra una dipendenza e la sua implementazione non è sempre esplicita. Una dipendenza può essere risolta in fase di esecuzione e influenzata da vari parametri. Il codice diventa più difficile da comprendere e eseguire il debug
  • Tempo di avvio più lento
  • Maturità (al momento): nessuna delle soluzioni attuali è veramente popolare al momento, quindi non così tanti tutorial, nessun ecosistema, non testato in battaglia.
  • Alcuni contenitori DI non funzioneranno bene con i bundler di moduli come Browserify e Webpack.

Come per tutto ciò che riguarda lo sviluppo del software, scegliendo tra DI o require dipende dalle tue esigenze, dalla tua complessità del sistema e dal tuo stile di programmazione.


61
2017-12-09 01:15



Ho anche scritto un modulo per realizzare questo, si chiama ricablare. Basta usare npm install rewire e poi:

var rewire = require("rewire"),
    myModule = rewire("./path/to/myModule.js"); // exactly like require()

// Your module will now export a special setter and getter for private variables.
myModule.__set__("myPrivateVar", 123);
myModule.__get__("myPrivateVar"); // = 123


// This allows you to mock almost everything within the module e.g. the fs-module.
// Just pass the variable name as first parameter and your mock as second.
myModule.__set__("fs", {
    readFile: function (path, encoding, cb) {
        cb(null, "Success!");
    }
});
myModule.readSomethingFromFileSystem(function (err, data) {
    console.log(data); // = Success!
});

Sono stato ispirato da Iniettore di Nathan MacInnes ma ha usato un approccio diverso. Io non uso vm per valutare il modulo di test, infatti, utilizzo la richiesta del nodo stesso. In questo modo il tuo modulo si comporta esattamente come se fosse utilizzato require() (eccetto le tue modifiche). Anche il debug è pienamente supportato.


37
2018-06-04 09:32



So che questo thread è piuttosto vecchio a questo punto, ma ho pensato di entrare in sintonia con i miei pensieri su questo. Il TL; DR è che, a causa della natura non tipizzata e dinamica di JavaScript, si può fare davvero molto senza ricorrere al modello di dipendenza (DI) o all'utilizzo di un framework DI. Tuttavia, man mano che un'applicazione si espande e diventa più complessa, DI può sicuramente aiutare la manutenibilità del tuo codice.

DI in C #

Per capire perché DI non è così importante in JavaScript, è utile guardare un linguaggio fortemente tipizzato come C #. (Chiede scusa a chi non conosce C #, ma dovrebbe essere abbastanza facile da seguire.) Diciamo che abbiamo un'app che descrive una macchina e il suo clacson. Definiresti due classi:

class Horn
{
    public void Honk()
    {
        Console.WriteLine("beep!");
    }
}

class Car
{
    private Horn horn;

    public Car()
    {
        this.horn = new Horn();
    }

    public void HonkHorn()
    {
        this.horn.Honk();
    }
}

class Program
{
    static void Main()
    {
        var car = new Car();
        car.HonkHorn();
    }
}

Ci sono alcuni problemi con la scrittura del codice in questo modo.

  1. Il Car la classe è strettamente accoppiata alla particolare implementazione del corno nel Horn classe. Se vogliamo cambiare il tipo di clacson usato dalla macchina, dobbiamo modificare il Car classe anche se il suo uso del clacson non cambia. Ciò rende anche difficile il test perché non possiamo testare il Car classe in isolamento dalla sua dipendenza, il Horn classe.
  2. Il Car classe è responsabile per il ciclo di vita del Horn classe. In un semplice esempio come questo non è un grosso problema, ma nelle vere applicazioni le dipendenze avranno dipendenze, che avranno dipendenze, ecc. Carla classe dovrebbe essere responsabile della creazione dell'intero albero delle sue dipendenze. Questo non è solo complicato e ripetitivo, ma viola la "singola responsabilità" della classe. Dovrebbe concentrarsi sull'essere un'auto, non creare istanze.
  3. Non c'è modo di riutilizzare le stesse istanze di dipendenza. Ancora una volta, questo non è importante in questa applicazione giocattolo, ma considera una connessione al database. Normalmente si dispone di un'unica istanza condivisa nell'applicazione.

Ora, facciamo un refactoring per usare un modello di iniezione di dipendenza.

interface IHorn
{
    void Honk();
}

class Horn : IHorn
{
    public void Honk()
    {
        Console.WriteLine("beep!");
    }
}

class Car
{
    private IHorn horn;

    public Car(IHorn horn)
    {
        this.horn = horn;
    }

    public void HonkHorn()
    {
        this.horn.Honk();
    }
}

class Program
{
    static void Main()
    {
        var horn = new Horn();
        var car = new Car(horn);
        car.HonkHorn();
    }
}

Abbiamo fatto due cose fondamentali qui. Innanzitutto, abbiamo introdotto un'interfaccia che la nostra Horn strumenti di classe. Questo ci permette di codificare il Car classe per l'interfaccia invece della particolare implementazione. Ora il codice potrebbe prendere tutto ciò che implementa IHorn. Secondo, abbiamo tolto l'istanziazione del corno Car e passarlo invece. Questo risolve i problemi di cui sopra e lo lascia alla funzione principale dell'applicazione per gestire le istanze specifiche e i loro cicli di vita.

Ciò significa che si potrebbe introdurre un nuovo tipo di clacson per l'auto da usare senza toccare il Car classe:

class FrenchHorn : IHorn
{
    public void Honk()
    {
        Console.WriteLine("le beep!");
    }
}

Il principale potrebbe semplicemente iniettare un'istanza del FrenchHorn classe invece. Questo semplifica enormemente i test. Potresti creare un MockHorn classe da iniettare nel Car costruttore per assicurarsi di testare solo il Car classe in isolamento.

L'esempio sopra mostra l'iniezione manuale delle dipendenze. Tipicamente DI è fatto con un quadro (ad es. Unità o Ninject nel mondo C #). Questi framework eseguiranno tutto il cablaggio delle dipendenze camminando sul grafico delle dipendenze e creando istanze in base alle esigenze.

The Standard Node.js Way

Ora diamo un'occhiata allo stesso esempio in Node.js. Probabilmente rompiamo il nostro codice in 3 moduli:

// horn.js
module.exports = {
    honk: function () {
        console.log("beep!");
    }
};

// car.js
var horn = require("./horn");
module.exports = {
    honkHorn: function () {
        horn.honk();
    }
};

// index.js
var car = require("./car");
car.honkHorn();

Poiché JavaScript non è tipizzato, non abbiamo lo stesso accoppiamento stretto che avevamo prima. Non c'è bisogno di interfacce (né esistono) come car il modulo cercherà solo di chiamare il honk metodo su qualunque cosa horn esportazioni di moduli.

Inoltre, perché Node's require memorizza tutto, i moduli sono essenzialmente singleton memorizzati in un contenitore. Qualsiasi altro modulo che esegue a require sul horn il modulo otterrà la stessa identica istanza. Questo rende molto semplice la condivisione di oggetti singleton come le connessioni di database.

Ora c'è ancora il problema che il car modulo è responsabile per il recupero della propria dipendenza horn. Se volessi che l'auto usasse un modulo diverso per il suo clacson, dovresti cambiare il require dichiarazione nel car modulo. Questa non è una cosa molto comune da fare, ma causa problemi con i test.

Il modo abituale con cui le persone gestiscono il problema del test è con proxyquire. A causa della natura dinamica di JavaScript, proxyquire intercetta le chiamate per richiedere e restituisce eventuali stub / mock forniti.

var proxyquire = require('proxyquire');
var hornStub = {
    honk: function () {
        console.log("test beep!");
    }
};

var car = proxyquire('./car', { './horn': hornStub });

// Now make test assertions on car...

Questo è più che sufficiente per la maggior parte delle applicazioni. Se funziona per la tua app, fallo con esso. Tuttavia, nella mia esperienza man mano che le applicazioni diventano più grandi e complesse, il mantenimento di codice come questo diventa più difficile.

DI in JavaScript

Node.js è molto flessibile. Se non sei soddisfatto del metodo di cui sopra, puoi scrivere i tuoi moduli usando il modello di iniezione delle dipendenze. In questo modello, ogni modulo esporta una funzione di fabbrica (o un costruttore di classi).

// horn.js
module.exports = function () {
    return {
        honk: function () {
            console.log("beep!");
        }
    };
};

// car.js
module.exports = function (horn) {
    return {
        honkHorn: function () {
            horn.honk();
        }
    };
};

// index.js
var horn = require("./horn")();
var car = require("./car")(horn);
car.honkHorn();

Questo è molto analogo al metodo C # in precedenza in quanto il index.js il modulo è responsabile, ad esempio, dei cicli di vita e del cablaggio. Il test delle unità è abbastanza semplice in quanto è possibile passare in derisioni / stub alle funzioni. Di nuovo, se questo è abbastanza buono per la tua applicazione.

Bolus DI Framework

A differenza di C #, non esistono quadri DI standard stabiliti per aiutare nella gestione delle dipendenze. Esistono numerosi framework nel registro di NPM ma nessuno ha un'adozione diffusa. Molte di queste opzioni sono già state citate nelle altre risposte.

Non ero particolarmente contento di nessuna delle opzioni disponibili, quindi ho scritto il mio bolo. Bolo è progettato per funzionare con il codice scritto nello stile DI sopra e cerca di essere molto ASCIUTTO e molto semplice. Usando lo stesso identico car.js e horn.js moduli sopra, è possibile riscrivere il index.js modulo con bolo come:

// index.js
var Injector = require("bolus");
var injector = new Injector();
injector.registerPath("**/*.js");

var car = injector.resolve("car");
car.honkHorn();

L'idea di base è creare un iniettore. Si registrano tutti i moduli nell'iniettore. Quindi risolvi semplicemente ciò di cui hai bisogno. Bolo percorre il grafico delle dipendenze e crea e inserisce le dipendenze secondo necessità. Non si risparmia molto in un esempio di giocattolo come questo, ma in grandi applicazioni con alberi di dipendenza complicati i risparmi sono enormi.

Il bolo supporta un sacco di funzioni eleganti come dipendenze opzionali e globalmente test, ma ci sono due vantaggi chiave che ho visto relativamente all'approccio Node.js standard. Innanzitutto, se hai molte applicazioni simili, puoi creare un modulo privato npm per la tua base che crea un iniettore e registra su di esso oggetti utili. Quindi le tue app specifiche possono aggiungerle, sostituirle e risolverle se necessario in modo molto simile a come AngularJS di l'iniettore funziona In secondo luogo, è possibile utilizzare bolo per gestire vari contesti di dipendenze. Ad esempio, è possibile utilizzare il middleware per creare un injector figlio per richiesta, registrare l'id utente, l'id di sessione, il logger, ecc. Sull'iniettore insieme a tutti i moduli a seconda di quelli. Quindi risolvi ciò che è necessario per servire le richieste. Ciò fornisce istanze dei moduli per richiesta e impedisce di passare il registratore, ecc. A ogni chiamata di funzione del modulo.


28
2018-02-20 20:05



ho costruito elettrolito solo per questo scopo. Le altre soluzioni per l'iniezione di dipendenza là fuori erano troppo invasive per i miei gusti, e scherzavano con il globale require è una mia particolare lamentela.

L'elettrolita abbraccia i moduli, in particolare quelli che esportano una funzione di "configurazione" come si vede nel middleware Connect / Express. In sostanza, questi tipi di moduli sono solo fabbriche per alcuni oggetti restituiti.

Ad esempio, un modulo che crea una connessione al database:

var mysql = require('mysql');

exports = module.exports = function(settings) {
  var connection = mysql.createConnection({
    host: settings.dbHost,
    port: settings.dbPort
  });

  connection.connect(function(err) {
    if (err) { throw err; }
  });

  return connection;
}

exports['@singleton'] = true;
exports['@require'] = [ 'settings' ];

Quello che vedi in fondo sono annotazioni, un ulteriore bit di metadati che Electrolyte utilizza per istanziare e iniettare dipendenze, collegando automaticamente i componenti dell'applicazione.

Per creare una connessione al database:

var db = electrolyte.create('database');

L'elettrolita attraversa transitivamente il @require'd dipendenze e inietta le istanze come argomenti per la funzione esportata.

La chiave è che questo è minimamente invasivo. Questo modulo è completamente utilizzabile, indipendentemente dallo stesso Electrolyte. Ciò significa che i tuoi test unitari possono essere testati solo il modulo sotto test, passando in oggetti finti senza bisogno di ulteriori dipendenze per ricablare gli interni.

Quando si esegue l'applicazione completa, Electrolyte interviene a livello di inter-modulo, collegando le cose insieme senza bisogno di globali, singoletti o tubature eccessive.


16
2017-11-26 05:51



Di recente ho controllato questo thread per lo stesso motivo dell'OP: la maggior parte delle librerie che ho incontrato temporaneamente riscrivono l'istruzione require. Ho avuto diversi gradi di successo con questo metodo, e così ho finito per utilizzare il seguente approccio.

Nel contesto di un'applicazione espressa: avvolgo app.js in un file bootstrap.js:

var path = require('path');
var myapp = require('./app.js');

var loader = require('./server/services/loader.js');

// give the loader the root directory
// and an object mapping module names 
// to paths relative to that root
loader.init(path.normalize(__dirname), require('./server/config/loader.js')); 

myapp.start();

La mappa dell'oggetto passata al caricatore ha il seguente aspetto:

// live loader config
module.exports = {
    'dataBaseService': '/lib/dataBaseService.js'
}

// test loader config
module.exports = {
    'dataBaseService': '/mocks/dataBaseService.js'
    'otherService' : {other: 'service'} // takes objects too...
};

Quindi, piuttosto che chiamare direttamente richiedono ...

var myDatabaseService = loader.load('dataBaseService');

Se nel caricatore non è presente alcun alias, per impostazione predefinita sarà sufficiente un normale requisito. Questo ha due vantaggi: posso scambiare qualsiasi versione della classe e rimuovere la necessità utilizzare i nomi dei percorsi relativi in ​​tutta l'applicazione (quindi se ho bisogno di una lib personalizzata sotto o al di sopra del file corrente, non ho bisogno di attraversare, e richiede che memorizzerà il modulo nella cache con la stessa chiave). Mi consente inoltre di specificare i mock in qualsiasi punto dell'app, piuttosto che nella suite di test immediata.

Ho appena pubblicato un piccolo modulo npm per comodità:

https://npmjs.org/package/nodejs-simple-loader


5
2018-02-08 13:20



Ho esaminato questo me stesso. Non mi piace l'introduzione di librerie di utilità di dipendenza magiche che forniscono meccanismi per dirottare le importazioni di moduli. Invece mi è venuta in mente una "linea guida del design" per consentire al mio team di indicare in modo esplicito quali dipendenze possono essere derise introducendo un'esportazione di funzioni di fabbrica all'interno dei miei moduli.

Faccio un ampio uso delle funzionalità di ES6 per i parametri e la destrutturazione al fine di evitare alcuni tipi di piastre e fornire un meccanismo di sovrascrittura delle dipendenze con nome.

Ecco un esempio:

import foo from './utils/foo';
import bob from './utils/bob';

// We export a factory which accepts our dependencies.
export const factory = (dependencies = {}) => {
  const {
    // The 'bob' dependency.  We default to the standard 'bob' imp if not provided.
    $bob = bob, 
    // Instead of exposing the whole 'foo' api, we only provide a mechanism
    // with which to override the specific part of foo we care about.
    $doSomething = foo.doSomething // defaults to standard imp if none provided.
  } = dependencies;  

  return function bar() {
    return $bob($doSomething());
  }
}

// The default implementation, which would end up using default deps.
export default factory();

Ed ecco un esempio del suo utilizzo

import { factory } from './bar';

const underTest = factory({ $bob: () => 'BOB!' }); // only override bob!
const result = underTest();

Scusa la sintassi ES6 per chi non ha familiarità con esso.


5
2018-01-10 17:21



Mi è sempre piaciuta la semplicità del concetto di IoC: "Non devi sapere nulla sull'ambiente, verrai chiamato da qualcuno quando necessario"

Ma tutte le implementazioni IoC che ho visto hanno fatto esattamente il contrario: ingombrano il codice con ancora più cose che senza. Così, ho creato il mio IoC che funziona come mi piacerebbe che fosse - rimane nascosto e invisibile al 90% del tempo.

È usato nel framework web MonoJS http://monojs.org 

Sto parlando di cose semplici, come la condivisione di un oggetto di connessione al database, quindi   lontano, ma non ho trovato una soluzione che mi soddisfi.

È fatto in questo modo: registra il componente una volta in configurazione.

app.register 'db', -> 
  require('mongodb').connect config.dbPath

E usalo ovunque

app.db.findSomething()

È possibile visualizzare il codice di definizione del componente completo (con connessione DB e altri componenti) qui https://github.com/sinizinairina/mono/blob/master/mono.coffee

Questo è l'unico posto in cui devi dire a IoC cosa fare, dopo che tutti questi componenti verranno creati e cablati automaticamente e non dovrai più vedere il codice IoC specifico nella tua applicazione.

Lo stesso IoC https://github.com/alexeypetrushin/miconjs


2
2018-05-20 04:29



Penso che abbiamo ancora bisogno di Dependency Injection in Nodejs perché allenta le dipendenze tra i servizi e rende più chiara l'applicazione.

Ispirato da Quadro di primavera, Implemento anche il mio modulo per supportare l'integrazione delle dipendenze in Nodejs. Il mio modulo è anche in grado di rilevare il code changes e auto reload i servizi senza riavviare la tua applicazione.

Visita il mio progetto a: Buncha - Contenitore IoC

Grazie!


2
2018-06-23 13:19



La realtà è che puoi testare il tuo node.js senza contenitore IoC perché JavaScript è un linguaggio di programmazione davvero dinamico e puoi modificare quasi tutto in fase di esecuzione.

Considera quanto segue:

import UserRepository from "./dal/user_repository";

class UserController {
    constructor() {
        this._repository = new UserRepository();
    }
    getUsers() {
        this._repository.getAll();
    }
}

export default UserController;

In questo modo è possibile ignorare l'accoppiamento tra componenti in fase di esecuzione. Mi piace pensare che dovremmo mirare a disaccoppiare i nostri moduli JavaScript.

L'unico modo per ottenere il vero disaccoppiamento è rimuovendo il riferimento al UserRepository:

class UserController {
    constructor(userRepository) {
        this._repository = userRepository;
    }
    getUsers() {
        this._repository.getAll();
    }
}

export default UserController;

Ciò significa che da qualche altra parte dovrai fare la composizione dell'oggetto:

import UserRepository from "./dal/user_repository";
import UserController from "./dal/user_controller";

export default new UserController(new UserRepository());

Mi piace l'idea di delegare la composizione dell'oggetto a un contenitore IoC. Puoi saperne di più su questa idea nell'articolo Lo stato corrente di inversione delle dipendenze in JavaScript. L'articolo cerca di ridimensionare alcuni "miti del contenitore IoC JavaScript":

Mito 1: non c'è posto per i contenitori IoC in JavaScript

Mito 2: non abbiamo bisogno di contenitori IoC, abbiamo già dei caricatori di moduli!

Mito 3: inversione delle dipendenze === iniezione di dipendenze

Se ti piace anche l'idea di usare un contenitore IoC potresti dare un'occhiata a InversifyJS. L'ultima versione (2.0.0) supporta molti casi d'uso:

  • Moduli del kernel
  • Middleware del kernel
  • Utilizza classi, stringhe letterali o simboli come identificatori di dipendenza
  • Iniezione di valori costanti
  • Iniezione di costruttori di classi
  • Iniezione di fabbriche
  • Fabbrica automatica
  • Iniezione di fornitori (fabbrica asincrona)
  • Gestori di attivazione (utilizzati per iniettare proxy)
  • Iniezioni multiple
  • Tag contrassegnati
  • Decoratori di tag personalizzati
  • Associazioni con nome
  • Binding contestuali
  • Eccezioni amichevoli (ad esempio dipendenze circolari)

Puoi saperne di più a riguardo InversifyJS.


2
2018-01-27 09:23