有一个正式配方可以使用InversifyJS注入一个函数。基本上,我们定义了一个助手函数,它将返回一个给定函数func的匆匆版本,并使用container.get(...)解析其所有依赖项。
import { container } from "./inversify.config"
function bindDependencies(func, dependencies) {
let injections = dependencies.map((dependency) => {
return container.get(dependency);
});
return func.bind(func, ...injections);
}
export { bindDependencies };我们就这样用它:
import { bindDependencies } from "./utils/bindDependencies";
import { TYPES } from "./constants/types";
function testFunc(something, somethingElse) {
console.log(`Injected! ${something}`);
console.log(`Injected! ${somethingElse}`);
}
testFunc = bindDependencies(testFunc, [TYPES.something, TYPES.somethingElse]);
export { testFunc };我想自动注入函数,而不显式地将它的依赖项提供给bindDependencies,可能是基于函数的参数名称。就像这样:
import { default as express, Router } from 'express';
import { bindDependencies } from '../injector/injector.utils';
import { AuthenticationMiddleware } from './authentication/authentication.middleware';
import { UsersMiddleware } from './users/users.middleware';
import { ENDPOINTS } from '../../../../common/endpoints/endpoints.constants';
function getRouter(
authenticationMiddleware: AuthenticationMiddleware,
usersMiddleware: UsersMiddleware,
): express.Router {
const router: express.Router = Router();
const requireAnonymity: express.Handler = authenticationMiddleware.requireAnonymity.bind(authenticationMiddleware);
const requireAuthentication: express.Handler = authenticationMiddleware.requireAuthentication.bind(authenticationMiddleware);
router.route(ENDPOINTS.AUTHENTICATION)
.put(requireAnonymity, authenticationMiddleware.login.bind(authenticationMiddleware))
.delete(requireAuthentication, authenticationMiddleware.logout.bind(authenticationMiddleware));
router.route(ENDPOINTS.USER)
.put(requireAnonymity, usersMiddleware.register.bind(usersMiddleware))
.post(requireAuthentication, usersMiddleware.update.bind(usersMiddleware))
.delete(requireAuthentication, usersMiddleware.remove.bind(usersMiddleware));
return router;
}
const router: express.Router = invoke(getRouter);
export { router as Router };注意,在这种情况下,我只想调用注入的函数一次,并得到它的返回值,这就是我要导出的,所以也许有一个更好的方法来完成这个任务,而不需要将代码包装在函数中,但是我认为直接在复合根之外使用container.get(...)并不是一个好主意,因为这个模块的依赖关系不清楚,并且可能分布在它的所有行中。此外,导出该函数将简化测试。
回到我的问题上,我的invoke函数如下所示:
function invoke<T>(fn: Function): T {
const paramNames: string[] = getParamNames(fn);
return fn.apply(null, paramNames.map((paramName: string)
=> container.get( (<any>container).map[paramName.toUpperCase()] ))) as T;
}对于getParamNames,我使用这里提出的解决方案之一:如何从javascript动态获取函数参数名称/值
(<any>container).map是我在创建容器之后在inversify.config.ts中创建的一个对象,它链接了所有依赖项的键和真正的键的字符串表示形式,而不管它的类型(在本例中,只有symbol或Function):
const container: Container = new Container();
container.bind<FooClass>(FooClass).toSelf();
...
const map: ObjectOf<any> = {};
(<any>container)._bindingDictionary._map
.forEach((value: any, key: Function | symbol) => {
map[(typeof key === 'symbol'
? Symbol.keyFor(key) : key.name).toUpperCase()] = key;
});
(<any>container).map = map;有人知道是否有更好的方法来做这件事,或者有什么重要的理由不去做?
发布于 2017-05-17 11:32:44
使用函数参数名称的主要问题是压缩代码时可能出现的问题:
function test(foo, bar) {
console.log(foo, bar);
}变成:
function test(a,b){console.log(a,b)},因为您在Node.js应用程序中工作,所以您可能没有使用压缩,所以这对您的来说不应该是个问题。
我认为你的解决方案是一个很好的时间解决方案。如果您查看TypeScript地图,在“未来”一节中我们可以看到:
这意味着今后InversifyJS将允许您执行以下操作:
注意:假设
AuthenticationMiddleware和UsersMiddleware是类。
@injectable()
function getRouter(
authenticationMiddleware: AuthenticationMiddleware,
usersMiddleware: UsersMiddleware,
): express.Router {
const router: express.Router = Router();
const requireAnonymity: express.Handler = authenticationMiddleware.requireAnonymity.bind(authenticationMiddleware);
const requireAuthentication: express.Handler = authenticationMiddleware.requireAuthentication.bind(authenticationMiddleware);
router.route(ENDPOINTS.AUTHENTICATION)
.put(requireAnonymity, authenticationMiddleware.login.bind(authenticationMiddleware))
.delete(requireAuthentication, authenticationMiddleware.logout.bind(authenticationMiddleware));
router.route(ENDPOINTS.USER)
.put(requireAnonymity, usersMiddleware.register.bind(usersMiddleware))
.post(requireAuthentication, usersMiddleware.update.bind(usersMiddleware))
.delete(requireAuthentication, usersMiddleware.remove.bind(usersMiddleware));
return router;
}或如下:
注意:假设
AuthenticationMiddleware和UsersMiddleware是接口。
@injectable()
function getRouter(
@inject("AuthenticationMiddleware") authenticationMiddleware: AuthenticationMiddleware,
@inject("UsersMiddleware") usersMiddleware: UsersMiddleware,
): express.Router {
const router: express.Router = Router();
const requireAnonymity: express.Handler = authenticationMiddleware.requireAnonymity.bind(authenticationMiddleware);
const requireAuthentication: express.Handler = authenticationMiddleware.requireAuthentication.bind(authenticationMiddleware);
router.route(ENDPOINTS.AUTHENTICATION)
.put(requireAnonymity, authenticationMiddleware.login.bind(authenticationMiddleware))
.delete(requireAuthentication, authenticationMiddleware.logout.bind(authenticationMiddleware));
router.route(ENDPOINTS.USER)
.put(requireAnonymity, usersMiddleware.register.bind(usersMiddleware))
.post(requireAuthentication, usersMiddleware.update.bind(usersMiddleware))
.delete(requireAuthentication, usersMiddleware.remove.bind(usersMiddleware));
return router;
}https://stackoverflow.com/questions/43920168
复制相似问题