使Angular模块容易互换

huangapple go评论53阅读模式
英文:

Make Angular modules easily exchangeable

问题

假设有两个特性模块"sql-connector"和"nosql-connector",可以在根模块中导入:

...
import { SqlConnectorModule } from './sql-connector/sql-connector.module';
@NgModule({ 
  ...
  imports: [ ..., SqlConnectorModule ]
  ...})
export class AppModule { }

这两个特性模块都导出了一个连接器类,用于管理连接和事务。这些连接器类具有类似的结构,可以将它们视为都实现了相同的接口。要在任何消费者类中应用连接器类,我们必须导入连接器。导入路径取决于模块.../sql-connector/connector.../nosql-connector/connector

是否可以以这种方式组织代码,无论是在app.modules.ts文件中导入sql-还是nosql-连接器模块,都不必更改任何消费者的导入指令?

如果不行,是否有其他模式可以使连接器可以轻松互换,并能够从主/根/配置文件中控制交换?

英文:

Assume there are 2 feature modules "sql-connector" and "nosql-connector", which can be imported in the root module:

...
import { SqlConnectorModule } from './sql-connector/sql-connector.module';
@NgModule({ 
  ...
  imports: [ ..., SqlConnectorModule ]
  ...})
export class AppModule { }

Both feature modules are exported a connector class, that managed connection and transactions. The connector classes have similar structure, comparable to if both would implement the same interface. To apply connector class in any consumer class, we have to import the connector. The import path depends on the module .../sql-connector/connector or .../nosql-connector/connector.

Is it possible to organize code in that way, no matter if sql- or nosql-connector module is imported in app.modules.ts file, then you don't have to exchange every import directive of any consumer?

If not, is there a other pattern to make connector exchangeable with min effort and control the exchange from main/root/config file?

答案1

得分: 2

提供者覆盖通常用于此目的。

首先,不要使用模块,只使用服务(如果我理解连接器的用途,应该不需要模块)。

接下来,声明一个接口或超类,它将对两个连接器都通用:

declare interface IConnector {
  connect(): void;
  disconnect(): void;
}

export class ConnectorBase {
  connect() {}
  disconnect() {}
}

将此接口实现到两个服务中:

export class SqlConnector implements IConnector {}
export class NoSqlConnector implements IConnector {}

export class SqlConnector extends ConnectorBase {
  override connect() {}
  override disconnect() {}
}
export class NoSqlConnector extends ConnectorBase {
  override connect() {}
  override disconnect() {}
}

最后,在模块中要切换时,覆盖提供者:

providers: [
  {
    provide: IConnector // 或者使用 ConnectorBase,如果接口不起作用
    useClass: SqlConnector
  }
],

您可以在每个模块基础上进行提供者覆盖,因此每个模块都可以有自己的连接器。如果您不提供一个,那么将使用应用程序模块的连接器。

另一种解决方案是使用文件替换,但这意味着整个应用程序中将使用一个连接器,并且要更改它,您需要使用特定环境构建您的应用程序(ng build -c nosql-dev)。

英文:

Provider overriding is usually used for that.

First of all, don't use modules, but services only (you shouldn't need a module if I get what the connectors are used for).

Next, declare an interface or a super class that will be common to both connectors :

declare interface IConnector {
  connect(): void;
  disconnect(): void;
}

export class ConnectorBase {
  connect() {}
  disconnect() {}
}

Implement this interface into both services :

export class SqlConnector implements IConnector {}
export class NoSqlConnector implements IConnector {}

export class SqlConnector extends ConnectorBase {
  override connect() {}
  override disconnect() {}
}
export class NoSqlConnector extends ConnectorBase {
  override connect() {}
  override disconnect() {}
}

Finally, when you want to switch, in your module, override the provider :

providers: [
  {
    provide: IConnector // ConnectorBase if it does not work with interfaces
    useClass: SqlConnector
  }
],

You can use the overriding on a per-module basis, so each module can have its own connector. If you don't provide one, then the one from app module will be used.

The other solution is to use file replacements, but it implies that a connector will be used in the whole application, and to change it, you build your application with a specific environment (ng build -c nosql-dev)

答案2

得分: -1

// tsconfig.json
{
    "paths": {
        "@db/*": ["path/to/[sql-connector|nosql-connector]/*"]
    }
}
import { SqlConnectorModule } from '@db/sql-connector.module';

使用此别名,您只需要在配置文件中更改别名的路径(动态或静态)。

英文:

You can try making path alias for that:

// tsconfig.json
{
    "paths": {
        "@db/*": ["path/to/[sql-connector|nosql-connector]/*"]
    }
}

and

import { SqlConnectorModule } from '@db/sql-connector.module';

with that alias all you need to do is change path of alias in configuration file (dynamically or statically)

huangapple
  • 本文由 发表于 2023年6月27日 20:46:06
  • 转载请务必保留本文链接:https://go.coder-hub.com/76565012.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定