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 };
この場合、注入された関数を 1 回呼び出してその戻り値を取得したいだけであることに注意してください。これはエクスポートしているものです。そのため、コードを関数にラップせずにこれを行うより良い方法があるかもしれませんが、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;
これを行うためのより良い方法があるかどうか、またはそれをしない重要な理由があるかどうかを知っている人はいますか?
関数の引数名の使用に関する主な問題は、コードを圧縮する際の潜在的な問題です。
function test(foo, bar) {
console.log(foo, bar);
}
になる:
function test(a,b){console.log(a,b)}
Node.js アプリで作業しているため、おそらく圧縮を使用していないため、これは問題にはなりません。
あなたの解決策は良い一時的な解決策だと思います。TypeScript Roapmapを確認すると、「Future」セクションで次のことがわかります。
- 関数式・矢印関数のデコレータ
これは、将来的に InversifyJS で次のことができるようになることを意味します。
注: とがclasses である
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;
}
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加