Malagu 框架本身也是一个复杂的项目,在框架的实现过程中,逐渐积累了一些好用的工具。

autoBind

在我们使用 IoC 能力的时候,原始提供的手动绑定对象到容器中这种方式,这种方式操作比较繁琐。Malagu 框架通过在模块入口文件调用 autoBind 方法自动绑定对象到模块,并将模块对象返回。另外 autoBind 方法支持一个回调函数,在回调函数中,仍然可以使用原生手动绑定的方式(在一些特殊情况,仍然需要这种方式)。

  1. // 某个模块入口文件
  2. import '../common';
  3. import { autoBind } from '@malagu/core';
  4. import '.';
  5. export default autoBind();
  1. export const CoreBackendModule = autoBind(bind => {
  2. bind(VALUE).toDynamicValue(ctx => {
  3. const namedMetadata = ctx.currentRequest.target.getNamedTag();
  4. const el = namedMetadata!.value.toString();
  5. const configProvider = ctx.container.get<ConfigProvider>(ConfigProvider);
  6. return configProvider.get(el);
  7. });
  8. });

ContainerUtil

Malagu 的核心基础设施是 IoC 容器,我们几乎把所有对象托管在 IoC 容器,让 IoC 容器负责这些对象的生命周期的管理。同时,框架也提供了一套装饰器 @Component()@Autowired() ,帮助我们把对象托管到 IoC 容器中,以及从容器中取出需要的对象。但是,装饰器有个缺陷,只有使用 Class 才好用。 ContainerUtil 工具类就是为了解决某些特殊情况下,没法使用 Class 诞生的。通过该工具类,我们可以方便获取需要的对象。不过,使用 ContainerUtil 有一个限制:必须要在应用启动中或者应用启动完成后,方可以使用。非常典型的使用场景:React 函数组件中使用。

  1. import * as React from 'react';
  2. import { ContainerUtil } from '@malagu/core';
  3. import { IconResolver } from './icon-protocol';
  4. const { useState, useEffect, Fragment } = React;
  5. export function Icon<T>(iconProps: T) {
  6. const [iconNode, setIconNode] = useState<React.ReactNode>([]);
  7. useEffect(() => {
  8. const resolve = async () => {
  9. const iconResolver = ContainerUtil.get<IconResolver<T>>(IconResolver);
  10. setIconNode(await iconResolver.resolve(iconProps));
  11. };
  12. resolve();
  13. }, [JSON.stringify(iconProps)]);
  14. return (<Fragment>{iconNode}</Fragment>);
  15. }

ConfigUtil

Malagu 的应用配置属性是由所有依赖的组件的属性合并而成。通过配置属性,我们可以方便地改变框架的默认行为,而不需要修改一行代码。当我们想要获取一个属性值的时候,可以通过 @Value() 声明式获取某个属性值。与 ContainerUtil 存在同样的限制:非 Class 场景不友好。我们通过 configUtil 工具类就能很方便的在非 Class 场景中获取属性值。使用 ConfigUtil 也有一个限制:必须要在应用启动中或者应用启动完成后,方可以使用。

  1. export function Logo(props: NavItemProps) {
  2. const { label, icon, ...rest } = ConfigUtil.get('malagu.shell.logo');
  3. props = { ...rest, ...props };
  4. return (<NavItem size="medium" gap="xsmall" label={label} icon={<Icon icon={icon}/>} hoverIndicator={false} activatable={false} {...props}/>);
  5. }

AnnotationUtil

AnnotationUtil.getType 获取目标对象属性或方法中的参数的类型信息,示例代码如下:

  1. AnnotationUtil.getType(target, targetKey, index); // 获取 target 对象中 targetKey 方法的第 index + 1 个参数的类型
  2. AnnotationUtil.getType(target, targetKey); // 获取 target 对象中 targetKey 属性的类型

Prioritizeable

根据优先级大小对数组进行同步或异步排序。

  1. Prioritizeable.prioritizeAllSync(this.contextInitializers).map(c => c.value);

getSuperClasses

获取指定类的所有基类。

getOwnMetadata

获取指定类以及所有基类的相关元信息。

Deferred

延迟获取某一对象的包装类。示例代码如下:

  1. const deferred = new Deferred(); // 创建 deferred 对象
  2. deferred.resole(value) // 成功时调用
  3. deferred.reject(error) // 失败时调用
  4. deferred.promise // 获取包装的 promise 对象

RequestMatcher

请求匹配器,支持 url 模式匹配。使用它可以验证当前请求的 url 是否符合某个 url 模式。该类的对象已经注入到 IoC 容器中,无需自己创建,请从容器中获取。

PathResolver

路径解析器。使用它可以把多个路径片段拼接到一起,它会帮您处理片段之间的 / 问题,以及适当的情况下,自动附加上应用路由前缀。该类的对象已经注入到 IoC 容器中,无需自己创建,请从容器中获取。