typescript - Utilizarea inversifyjs pentru a injecta legăturile containerului într-o instanță a unui obiect existent


Practic, mi-ar plăcea să fiu responsabil de construcția obiectului, apoi să folosesc inversify pentru a lega proprietățile care sunt decorate cu @inject.

Am crezut că aș putea folosi createChild pentru a lega tipul la o valoare folosind toConstantValue sau chiar toDynamicValue; totuși, se pare că niciuna dintre aceste metode nu face vreo legare a proprietăților.

Exemplu

import "reflect-metadata";
import { Container, inject, injectable } from "inversify";

const container = new Container();
container.bind(Container).toConstantValue(container);

@injectable()
class Foo {
  @inject(Container)
  public container: Container;
}

describe("inversify", () => {
  it("should inject for ctor", () => { //                    PASS
    const c = container.createChild();
    c.bind(Foo).toSelf();
    const result = c.get(Foo);
    expect(result.container).toBeDefined();
  });

  it("should inject for dynamic value", () => { //           FAIL
    const c = container.createChild();
    c.bind(Foo).toDynamicValue(() => new Foo());
    const result = c.get(Foo);
    expect(result.container).toBeDefined();
  });

  it("should inject for const value", () => { //             FAIL
    const c = container.createChild();
    c.bind(Foo).toConstantValue(new Foo());
    const result = c.get(Foo);
    expect(result.container).toBeDefined();
  });
});

Se pare că ar trebui să existe o modalitate ușoară de a lega proprietățile fără a amâna construcția obiectului în Container?

Răspuns #1

Ceea ce experimentați este un comportament așteptat, conform proiectării. Iată câteva detalii suplimentare:

laValoareDinamică

Despre primul caz de test. toDynamicValue este conceput pentru a fi folosit în cazurile în care InversifyJS nu poate crea o instanță, de exemplu, pentru că injectați ceva care este implementat de o bibliotecă terță. InversifyJS nu se implică în crearea instanței, și depinde de dvs. să creați instanța corect.

it("should inject for dynamic value", () => {L
  const c = container.createChild();
  c.bind(Foo).toDynamicValue(() => new Foo());
  const result = c.get(Foo);
  expect(result.container).toBeDefined();
});

Poți folosi parametrul context în toDynamicValue pentru a rezolva dependențele:

c.bind(Foo).toDynamicValue((context) => {
    const foo = new Foo();
    const container = context.container.get(Container)
    foo.container = container;
    return foo;
});

Notă: Poate că foo.container=context.container este suficient.

laValoareConstantă

Despre al doilea caz de testare:

it("should inject for const value", () => {
  const c = container.createChild();
  c.bind(Foo).toConstantValue(new Foo());
  const result = c.get(Foo);
  expect(result.container).toBeDefined();
});

Eșecul este așteptat. Atunci când folosești toConstantValue trebuie să furnizezi o valoare. Este responsabilitatea ta să creezi valoarea corect. În exemplul tău, folosești new Foo(), InversifyJS nu va interveni în crearea valorii deoarece toConstantValue este o funcționalitate concepută pentru a susține injectarea variabilelor în cazurile în care trebuie să injectezi ceva fără un constructor (de exemplu, process.env.SOME_ENV_VAR).