装饰器在任何其他混乱 "this" 上下文之前调用方法
Decorator to call a method before any other messes with "this" context
真正的问题
我想我找到了真正的问题,inversify
其他一切正常。
在原来的 post 中,我省略了部分代码,因为我认为它们不是导致问题的原因。
在我的 ICitiesRepo
实现中,我有一个方法 ensureDb
确保初始化一些 typeorm
属性,因为这个方法必须是异步的我不能只调用它构造函数因此应该在任何 CRUD 操作之前调用它,然后我创建了一个装饰器,目的是在 class:
中的任何其他方法之前调用 ensureDb
export const ensureCall = (method: string) => {
return (target: any) => {
for (const prop of Object.getOwnPropertyNames(target.prototype)) {
if (prop === method || prop === 'constructor') continue;
const originalMethod = target.prototype[prop];
if (originalMethod instanceof Function) {
target.prototype[prop] = async (...args: any[]) => {
await target.prototype[method]();
return originalMethod.apply(this, args);
};
}
}
};
};
这是用途:
@ensureCall('ensureDb')
@injectable()
class CitiesRepo implements ICitiesRepo {
@inject('CitiesWriteRepo') private readonly repo: IWriteRepo<City>;
async ensureDb() {
await this.repo.doSomething();
// repo is undefined because I messed up with the context
}
// interface implementation
}
如果我删除那个装饰器并在其他方法工作之前调用 ensureDb
:
const container = getContainer();
const citiesRepo: ICitiesRepo = container.get('CitiesRepo');
await citiesRepo.ensureDb();
const list = await citiesRepo.getAll(); // It works
是否可以解决这个问题或其他更好的方法来实现我想要做的事情?
原版post
我有一个带有通用存储库的项目,但我在使用 inversifyJS 注入存储库对象时遇到了一些问题。结构是这样的:
interface IWriteRepo<T> { /* interface members */ }
@injectable()
class WriteRepo<City> implements IWriteRepo<City> { /* interface implementation */ }
interface ICitiesRepo { /* interface members */ }
@injectable()
class CitiesRepo implements ICitiesRepo {
@inject('CitiesWriteRepo') private readonly repo: IWriteRepo<City>;
// interface implementation
}
interface ICitiesService { /* interface members */ }
@injeactable()
class CitiesService {
@inject('CitiesRepo') repo: ICitiesRepo;
// interface implementation
}
// binding
const container = new Container();
container.bind<IWriteRepo<City>>('CitiesWriteRepo').to(WriteRepo);
container.bind<ICitiesRepo>('CitiesRepo').to(CitiesRepo);
container.bind<ICitiesService>('CitiesService').to(CitiesService);
我正在使用节点应用程序测试代码,当我尝试获取通用存储库 (IWriteRepo<City>
) 和 CitiesRepo
我没有任何问题:
const container = getContainer();
const citiesRepo: ICitiesRepo = container.get('CitiesRepo'); // OK and prop repo injected correctly
const citiesWriteRepo: IWriteRepo<City> = container.get('CitiesWriteRepo'); // OK
尝试获取服务时出现问题:
const container = getContainer();
const citiesService: ICitiesService = container.get('CitiesService');
服务已正确注入,repo: ICitiesRepo
但通用“孙子”repo: IWriteRepo<City>
未定义。
知道如何解决吗?
编辑
我仍在努力找出问题所在。
现在我尝试将 class 注入构造函数,但发生了一些奇怪的事情:InversifyJS 正确注入依赖项,我将其分配给 属性 但是当我尝试使用它时它是未定义的。
interface ICitiesRepo { /* interface members */ }
@injectable()
class CitiesRepo implements ICitiesRepo {
private readonly repo: IWriteRepo<City>;
constructor(@inject('CitiesWriteRepo') repo: IWriteRepo<City>) {
console.log(repo); // result: WriteRepo {}
this.repo = repo;
console.log(this.repo); // result: WriteRepo {}
}
getAll() {
console.log(this.repo); // result: undefined
}
// interface implementation
}
你快了。你得到 undefined
因为你的装饰器中的 this
是未定义的,应该指的是你的目标的实例化实例。将该定义更改为常规函数调用而不是箭头函数应该可以解决问题。
export const ensureCall = (method: string) => {
return (target: any) => {
for (const prop of Object.getOwnPropertyNames(target.prototype)) {
if (prop === method || prop === 'constructor') continue;
const originalMethod = target.prototype[prop];
if (originalMethod instanceof Function) {
// Regular function declaration
target.prototype[prop] = async function(...args: any[]) {
await target.prototype[method]();
// Now `this` refers to an instantiated instance
return originalMethod.apply(this, args);
};
}
}
};
};
真正的问题
我想我找到了真正的问题,inversify
其他一切正常。
在原来的 post 中,我省略了部分代码,因为我认为它们不是导致问题的原因。
在我的 ICitiesRepo
实现中,我有一个方法 ensureDb
确保初始化一些 typeorm
属性,因为这个方法必须是异步的我不能只调用它构造函数因此应该在任何 CRUD 操作之前调用它,然后我创建了一个装饰器,目的是在 class:
ensureDb
export const ensureCall = (method: string) => {
return (target: any) => {
for (const prop of Object.getOwnPropertyNames(target.prototype)) {
if (prop === method || prop === 'constructor') continue;
const originalMethod = target.prototype[prop];
if (originalMethod instanceof Function) {
target.prototype[prop] = async (...args: any[]) => {
await target.prototype[method]();
return originalMethod.apply(this, args);
};
}
}
};
};
这是用途:
@ensureCall('ensureDb')
@injectable()
class CitiesRepo implements ICitiesRepo {
@inject('CitiesWriteRepo') private readonly repo: IWriteRepo<City>;
async ensureDb() {
await this.repo.doSomething();
// repo is undefined because I messed up with the context
}
// interface implementation
}
如果我删除那个装饰器并在其他方法工作之前调用 ensureDb
:
const container = getContainer();
const citiesRepo: ICitiesRepo = container.get('CitiesRepo');
await citiesRepo.ensureDb();
const list = await citiesRepo.getAll(); // It works
是否可以解决这个问题或其他更好的方法来实现我想要做的事情?
原版post
我有一个带有通用存储库的项目,但我在使用 inversifyJS 注入存储库对象时遇到了一些问题。结构是这样的:
interface IWriteRepo<T> { /* interface members */ }
@injectable()
class WriteRepo<City> implements IWriteRepo<City> { /* interface implementation */ }
interface ICitiesRepo { /* interface members */ }
@injectable()
class CitiesRepo implements ICitiesRepo {
@inject('CitiesWriteRepo') private readonly repo: IWriteRepo<City>;
// interface implementation
}
interface ICitiesService { /* interface members */ }
@injeactable()
class CitiesService {
@inject('CitiesRepo') repo: ICitiesRepo;
// interface implementation
}
// binding
const container = new Container();
container.bind<IWriteRepo<City>>('CitiesWriteRepo').to(WriteRepo);
container.bind<ICitiesRepo>('CitiesRepo').to(CitiesRepo);
container.bind<ICitiesService>('CitiesService').to(CitiesService);
我正在使用节点应用程序测试代码,当我尝试获取通用存储库 (IWriteRepo<City>
) 和 CitiesRepo
我没有任何问题:
const container = getContainer();
const citiesRepo: ICitiesRepo = container.get('CitiesRepo'); // OK and prop repo injected correctly
const citiesWriteRepo: IWriteRepo<City> = container.get('CitiesWriteRepo'); // OK
尝试获取服务时出现问题:
const container = getContainer();
const citiesService: ICitiesService = container.get('CitiesService');
服务已正确注入,repo: ICitiesRepo
但通用“孙子”repo: IWriteRepo<City>
未定义。
知道如何解决吗?
编辑
我仍在努力找出问题所在。 现在我尝试将 class 注入构造函数,但发生了一些奇怪的事情:InversifyJS 正确注入依赖项,我将其分配给 属性 但是当我尝试使用它时它是未定义的。
interface ICitiesRepo { /* interface members */ }
@injectable()
class CitiesRepo implements ICitiesRepo {
private readonly repo: IWriteRepo<City>;
constructor(@inject('CitiesWriteRepo') repo: IWriteRepo<City>) {
console.log(repo); // result: WriteRepo {}
this.repo = repo;
console.log(this.repo); // result: WriteRepo {}
}
getAll() {
console.log(this.repo); // result: undefined
}
// interface implementation
}
你快了。你得到 undefined
因为你的装饰器中的 this
是未定义的,应该指的是你的目标的实例化实例。将该定义更改为常规函数调用而不是箭头函数应该可以解决问题。
export const ensureCall = (method: string) => {
return (target: any) => {
for (const prop of Object.getOwnPropertyNames(target.prototype)) {
if (prop === method || prop === 'constructor') continue;
const originalMethod = target.prototype[prop];
if (originalMethod instanceof Function) {
// Regular function declaration
target.prototype[prop] = async function(...args: any[]) {
await target.prototype[method]();
// Now `this` refers to an instantiated instance
return originalMethod.apply(this, args);
};
}
}
};
};