Last active
May 28, 2020 19:54
-
-
Save gaogao-9/7ace1680cfe3ed44705028bd014f16ba to your computer and use it in GitHub Desktop.
TypeScriptでデコレータなしでDIするやつ
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export type Types = Record<string, symbol>; | |
export interface IDIContainerBindResult<T> { | |
to: (value: new () => T) => void; | |
toStatic: (value: T) => void; | |
} | |
export interface IDIContainer { | |
container: { | |
[k in Types[keyof Types]]: unknown; | |
}; | |
isStatic: { | |
[k in Types[keyof Types]]: boolean; | |
}; | |
bind<T>(key: Types[keyof Types]): IDIContainerBindResult<T>; | |
inject<T, U extends Iterable<unknown> = []>( | |
key: Types[keyof Types], | |
args?: U, | |
): T; | |
} | |
export const DIContainer: IDIContainer = { | |
container: {}, | |
isStatic: {}, | |
bind<T>(key: Types[keyof Types]): IDIContainerBindResult<T> { | |
return { | |
to(value): void { | |
DIContainer.container[key] = value; | |
DIContainer.isStatic[key] = false; | |
}, | |
toStatic(value): void { | |
DIContainer.container[key] = value; | |
DIContainer.isStatic[key] = true; | |
}, | |
}; | |
}, | |
inject<T, U extends Iterable<unknown> = []>( | |
key: Types[keyof Types], | |
args?: U, | |
): T { | |
if (!DIContainer.container[key]) { | |
throw new Error(`コンテナに登録されていないkeyを参照しました。`); | |
} | |
return DIContainer.isStatic[key] | |
? DIContainer.container[key] | |
: new DIContainer.container[key](...(args || [])); | |
}, | |
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export const Types = { | |
Knex: Symbol("Knex"), | |
Database: Symbol("Database"), | |
UserRepository: Symbol("UserRepository"), | |
UserController: Symbol("UserController"), | |
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// このファイルに書かれていることは実際はknex側の実装だったり、あるいはテスト用のMock Knexだったりします | |
export class Knex { | |
constructor(options: { url: string }) { | |
/* 以下実際はknex側で実装された何かが続く... */ | |
console.log(options.url); | |
} | |
from(query: string): this { | |
/* 以下実際はknex側で実装された何かが続く... */ | |
console.log(`from: ${query}`); | |
return this; | |
} | |
where(query: string, placeholder: Array<unknown>): this { | |
/* 以下実際はknex側で実装された何かが続く... */ | |
console.log(`where: ${query} ${placeholder}`); | |
return this; | |
} | |
find<T>(): T { | |
/* 以下knex側で実装された何かが続く... */ | |
const result: T = ({} as unknown) as T; | |
return result; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export interface IDatabaseOptions { | |
connectionURL: string; | |
} | |
export interface IDatabase { | |
connect(options: IDatabaseOptions): void; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { DIContainer } from "./DIContainer.ts"; | |
import { Types } from "./types.ts"; | |
import { IDatabase, IDatabaseOptions } from "./IDatabase.ts"; | |
import { Knex } from "./Knex.ts"; | |
export interface IKnexDatabase extends IDatabase { | |
client: Knex; | |
} | |
export class KnexDatabase implements IKnexDatabase { | |
client: Knex; | |
connect(options: IDatabaseOptions): void { | |
this.client = DIContainer.inject<Knex, ConstructorParameters<typeof Knex>>( | |
Types.Knex, | |
[{ url: options.connectionURL }], | |
); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { IDatabase } from "./IDatabase.ts"; | |
export interface IRepository { | |
database: IDatabase; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export type User = { | |
id: string; | |
name: string; | |
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { DIContainer } from "./DIContainer.ts"; | |
import { Types } from "./types.ts"; | |
import { IRepository } from "./IRepository.ts"; | |
import { IKnexDatabase } from "./KnexDatabase.ts"; | |
import { User } from "./User.ts"; | |
export interface IUserRepository extends IRepository { | |
find(id: string): User; | |
} | |
export class UserRepository implements IUserRepository { | |
database = DIContainer.inject<IKnexDatabase>(Types.Database); | |
public find(id: string): User { | |
return this.database.client | |
.from("user") | |
.where("user.id = ?", [id]) | |
.find<User>(); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export interface IController { | |
repository: IRepository; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { DIContainer } from "./DIContainer.ts"; | |
import { Types } from "./types.ts"; | |
import { IController } from "./IController.ts"; | |
import { IUserRepository } from "./UserRepository.ts"; | |
import { User } from "./User.ts"; | |
interface IUserController extends IController { | |
get(id: string): User; | |
post(user: User): void; | |
} | |
class UserController implements IUserController { | |
repository = DIContainer.inject<IUserRepository>(Types.UserRepository); | |
get(id: string): User { | |
return this.repository.find(id); | |
} | |
post(user: User): void { | |
throw new Error("Method not implemented."); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { DIContainer } from "./DIContainer.ts"; | |
import { Types } from "./types.ts"; | |
import { Knex } from "./Knex.ts"; | |
import { KnexDatabase } from "./KnexDatabase.ts"; | |
import { UserRepository } from "./UserRepository.ts"; | |
import { UserController } from "./UserController.ts"; | |
DIContainer.bind(Types.Knex).toStatic(new Knex()); | |
DIContainer.bind(Types.Database).toStatic(new KnexDatabase()); | |
DIContainer.bind(Types.UserRepository).to(UserRepository); | |
DIContainer.bind(Types.UserController).to(UserController); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment