Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Strange behavior of hierarchical DI #1513

Open
ilya2204 opened this issue May 29, 2023 · 1 comment
Open

Strange behavior of hierarchical DI #1513

ilya2204 opened this issue May 29, 2023 · 1 comment

Comments

@ilya2204
Copy link

This seems to be wrong behavior, doesn't it? I expect dependencies can't propagate from bottom to top, but that's what's happening right now

Steps to Reproduce (for bugs)

@injectable()
class B {}

@injectable()
class A {
  constructor(public readonly b: B) {}
}

const root = new Container({ defaultScope: "Singleton" });

root.bind(A).toSelf();
root.bind(B).toSelf();

const child = new Container({ defaultScope: "Singleton" });
child.parent = root;

child.bind(B).toSelf();

const a = child.get(A);
const bFromRoot = root.get(B);

// Expected to be true, but it's false, because A created with B from child container
console.log("equal", bFromRoot === a.b);

Expected Behavior

bFromRoot equals a.b

Current Behavior

bFromRoot not equals a.b

Your Environment

  • Version used: 6.0.1

Also, I expect if I remove B provider from root, I will get an error, but I don't get one

@TotooriaHyperion
Copy link

TotooriaHyperion commented Sep 12, 2023

same problem here:

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

@injectable()
class ModelA_inBoth {}

@injectable()
class ModelA2_inRoot {
  @inject(ModelA_inBoth)
  a1: ModelA_inBoth;
}

@injectable()
class ModelB_inRoot {
  @inject(ModelA_inBoth)
  a1: ModelA_inBoth;
}

@injectable()
class ModelC_inChild {
  @inject(ModelA_inBoth)
  a1: ModelA_inBoth;

  @inject(ModelA2_inRoot)
  a2: ModelA2_inRoot;
}

function test1() {
  const root = new Container({ defaultScope: "Singleton" });

  const child = root.createChild();

  root.bind(ModelA_inBoth).toSelf();
  root.bind(ModelA2_inRoot).toSelf(); // A2 -> A1
  root.bind(ModelB_inRoot).toSelf(); // B -> A1

  child.bind(ModelA_inBoth).toSelf();
  child.bind(ModelC_inChild).toSelf(); // C -> A2 -> A1

  const modelB = root.get(ModelB_inRoot); // root.B -> root.A1
  const modelC = child.get(ModelC_inChild); // child.C -> root.A2 -> child.A1

  // expect: child.C -> root.A2 -> root.A1
  // actual: child.C -> root.A2 -> child.A1
  // expect to be true, actual false
  console.log(
    "modelC.a2.a1 === modelB.a1, expect true",
    modelC.a2.a1 === modelB.a1
  );
  // expect: child.C -> root.A1 === root.B -> root.A1
  // actual: child.C -> child.A1 !== root.B -> root.A1
  // expect to be true, actual false
  console.log("modelC.a1 === modelB.a1, expect true", modelC.a1 === modelB.a1);
  // expect: child.C -> child.A1 !== child.C -> root.A2 -> root.A1
  // actual: child.C -> child.A1 === child.A -> root.A2 -> child.A1
  // expect to be false, actual true
  console.log(
    "modelC.a1 === modelC.a2.a1, expect false",
    modelC.a1 === modelC.a2.a1
  );
}

test1();

The problem is, root.A2 -> child.A1, which violates the hierarchical relations between containers.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: No status
Development

No branches or pull requests

2 participants