javascript - 将类型传递给依赖注入(inject)容器

标签 javascript node.js typescript dependency-injection inversifyjs

我在不使用 ORM 工具的情况下支持多个数据库。对于此示例,我将展示 Postgres 和 MSSQL UserQueries

的示例

enter image description here

我有一个接口(interface)IDataBase,多个数据库实现了这个接口(interface)。

@injectable()
export class MssqlDatabase implements IDatabase {
    public async connect(): Promise<void> {
    }

    public async disconnect(): Promise<void> {
    }
}

此外,我有定义查询的 IUserQueries 接口(interface)

export interface IUserQueries {
    fetchUsers(): Promise<QueryResult>;
}

QueryResult 是一个自定义类,用于确保每个数据库查询都为我的 API 返回相同的数据对象。我的 API 从目标接口(interface)调用特定查询。如果 mssql 是配置文件中的标识符,我的应用程序应该创建到 MSSQL 数据库的连接。但是我的 API 文件不应该关心并且不知道这一点(显然,这就是接口(interface)的作用)。

一个基本的例子是

@injectable()
export class UserRepository implements IUserRepository {
    public userQueries: IUserQueries;

    constructor(@inject(IoCTypes.IUserQueries) userQueries: IUserQueries) {
        this.userQueries = userQueries;
    }
}

现在事情变得棘手了。我的 DI 容器:

const container: Container = new Container();
container.bind<IUserQueries>(IoCTypes.IUserQueries).to(/* what? */);
export { container };

DI 容器不知道选择哪个查询文件。它可以是 MSSQLUserQueriesPostgresUserQueries。我怎么解决这个问题?可以在启动服务器 (app.ts) 时选择正确的查询,但据我所知,这个 DI 容器完全独立于应用程序,只是充当配置文件,所以我应该'传递一个抽象的 UserQueries 类。

最佳答案

你可以使用工厂模式:

interface IUserQueryFactory {
    get(): IUserQueries;
    get(type: string): IUserQueries;
}

class UserQueryFactory implements IUserQueryFactory {
    get(): IUserQueries {
        const defaultValue = config.database; // or whatever returns your "mssql" from config
        return this.get(defaultValue);
    }

    get(type: string): IUserQueries {
        switch (type) {
            case "mssql":
                return new MSSQLUserQueries();
            case "postgresql":
                return new PostgresUserQueries();
            default:
                return null;
        }
    }
}

const container: Container = new Container();
container.bind<IUserQueryFactory>(IoCTypes.IUserQueryFactory).to(UserQueryFactory);
container.bind<IUserQueries>(IoCTypes.IUserQueries).toDynamicValue((context: interfaces.Context) => { return context.container.get<IUserQueryFactory>(IoCTypes.IUserQueryFactory).get(); });
export { container };

我不确定我是否正确理解了整个语法,因为这没有经过测试,但我猜你明白了:

  1. IUserQueryFactory返回 IUserQueries基于输入类型或返回默认类型(在配置中定义)如果类型不是提供者
  2. IUserQueries 的默认实现基本都是通过IUserQueryFactory实现的这意味着创造 IUserQueries 的全部来源位于单一位置且易于维护。

关于javascript - 将类型传递给依赖注入(inject)容器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57627707/

相关文章:

javascript - 如何在 Node.js 中正确实现 "forgot/reset password"功能? (使用一次性 token )

javascript - 我应该使用 [innerHTML] 还是通常的方式(Angular 2)

typescript 泛型 : return instance of class parameter

javascript - g:submitButton- onclick不起作用

javascript - 依次单击两个元素

node.js - Node lambda 未写入 DynamoDB 且没有错误

javascript - async wait 实用函数同步?

typescript - 如何在Typescript中获取axios响应头

javascript - 让我的网站不留下 cookie

javascript - 无法通过 jquery 到达特定元素 : Undefined