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

[WIP] 带参数的类注入 #3

Open
hyj1991 opened this issue Mar 18, 2022 · 13 comments
Open

[WIP] 带参数的类注入 #3

hyj1991 opened this issue Mar 18, 2022 · 13 comments

Comments

@hyj1991
Copy link
Member

hyj1991 commented Mar 18, 2022

需求

import { Injectable, ScopeEnum } from "@artus/injection";

@Injectable({
  id: 'foo',
  scope: ScopeEnum.EXECUTION
})
export class Foo {
  #name: string;
  constructor(name: string) {
   this.#name = name;
  }

  say() {
    console.log(this.#name);
  }
}

每个 Execution 生命周期中实例化Foo 时如何通过 container 传入构造函数需要的参数,比如:

import { Inject } from "@artus/injection";

export class Bar {
  @Inject('foo')
  private foo;

  say() {
    this.foo.say();
  }
}
@hyj1991
Copy link
Member Author

hyj1991 commented Mar 18, 2022

@JerrysShan 帮忙看看这个目前可以实现不

@JerrysShan
Copy link
Collaborator

如果参数是可以注入的类型,目前可以通过这种形式传递参数

import { Injectable, Container } from '@artus/injection';
import "reflect-metadata";

const container = new Container('default');
@Injectable()
class Phone {
    dial() {
        console.log('dial phone')
    }
}

@Injectable()
class Person {
    public phone: Phone;
    constructor(phone: Phone) {
        this.phone = phone;

    }
}


container.set({ id: Phone });
container.set({ id: Person });

const person = container.get(Person);

person.phone.dial();

@JerrysShan
Copy link
Collaborator

不过也考虑过在get的时候,支持传递参数

@hyj1991
Copy link
Member Author

hyj1991 commented Mar 18, 2022

这种形式有个问题是,参数必须是 Injectable class,假如是纯参数好像没法处理,比如一个可变的 string

@hyj1991
Copy link
Member Author

hyj1991 commented Mar 18, 2022

我现在的做法是给一个 init 方法,拿到实例后手动调用下 init 方法将参数传入,不知道有没有办法在 injection 这个类库中做一些更好的处理

@JerrysShan
Copy link
Collaborator

这种形式有个问题是,参数必须是 Injectable class,假如是纯参数好像没法处理,比如一个可变的 string

这里不仅仅局限于class ,可以通过 @inject 注入其他容器中包含的值,但是前提是如果是值类型,必须提前放到容器中。

通过 init 方法是个解决方案, 也考虑过是不是 get 的时候可以传递参数

@hyj1991
Copy link
Member Author

hyj1991 commented Mar 18, 2022

但是前提是如果是值类型,必须提前放到容器中

这样看起来有冲突,对于 ScopeEnum.EXECUTION 原本就是每次运行时才会获取到的值用于对应 class 的初始化

@hyj1991
Copy link
Member Author

hyj1991 commented Mar 18, 2022

举个例子:

@Injectable({
  id: 'handle',
  scope: ScopeEnum.EXECUTION
});
class HandleRequest {
  constructor(req, res) {
    this.req = req;
    this.res = res;
  }
}

http.createServer((req, res)=> {
  const handle = container.get('handle'); // 这里的 req 和 res 有没有啥时机可以传进去
});

如果把参数放到 container.get 里面感觉怪怪的,reflect-metadata 能不能给 class 设置一个 slot,自动注入参数值

@JerrysShan
Copy link
Collaborator

一起看下这里怎么处理比较好吧

@hyj1991
Copy link
Member Author

hyj1991 commented Mar 18, 2022

@whxaxes 要不一起看看这个有没有优雅一些的实现呢

@whxaxes
Copy link
Member

whxaxes commented Mar 18, 2022

reflect-metadata 能不能给 class 设置一个 slot

这个可以的啊,元数据都是自己设的,只是你在 container.get('handle') 这个里面,如何更好的传递参数,要么是在 get 后面加个参数传进去,要么就用其他方式

@hyj1991
Copy link
Member Author

hyj1991 commented Jun 16, 2022

这里建议给 getgetAsync 增加参数,作为 CLASS_CONSTRUCTOR_ARGS 的补充

@hyj1991
Copy link
Member Author

hyj1991 commented Jun 16, 2022

这样可以使得 pipeline 重大部分场景无需显式访问内置 context 对象,所有需要的 execution 属性全都通过 Inject 来进行使用

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

No branches or pull requests

3 participants