Malagu 框架本身也是一个复杂的项目,在框架的实现过程中,逐渐积累了一些好用的工具。
autoBind
在我们使用 IoC 能力的时候,原始提供的手动绑定对象到容器中这种方式,这种方式操作比较繁琐。Malagu 框架通过在模块入口文件调用 autoBind 方法自动绑定对象到模块,并将模块对象返回。另外 autoBind 方法支持一个回调函数,在回调函数中,仍然可以使用原生手动绑定的方式(在一些特殊情况,仍然需要这种方式)。
// 某个模块入口文件import '../common';import { autoBind } from '@malagu/core';import '.';export default autoBind();
export const CoreBackendModule = autoBind(bind => {bind(VALUE).toDynamicValue(ctx => {const namedMetadata = ctx.currentRequest.target.getNamedTag();const el = namedMetadata!.value.toString();const configProvider = ctx.container.get<ConfigProvider>(ConfigProvider);return configProvider.get(el);});});
ContainerUtil
Malagu 的核心基础设施是 IoC 容器,我们几乎把所有对象托管在 IoC 容器,让 IoC 容器负责这些对象的生命周期的管理。同时,框架也提供了一套装饰器 @Component() 、 @Autowired() ,帮助我们把对象托管到 IoC 容器中,以及从容器中取出需要的对象。但是,装饰器有个缺陷,只有使用 Class 才好用。 ContainerUtil 工具类就是为了解决某些特殊情况下,没法使用 Class 诞生的。通过该工具类,我们可以方便获取需要的对象。不过,使用 ContainerUtil 有一个限制:必须要在应用启动中或者应用启动完成后,方可以使用。非常典型的使用场景:React 函数组件中使用。
import * as React from 'react';import { ContainerUtil } from '@malagu/core';import { IconResolver } from './icon-protocol';const { useState, useEffect, Fragment } = React;export function Icon<T>(iconProps: T) {const [iconNode, setIconNode] = useState<React.ReactNode>([]);useEffect(() => {const resolve = async () => {const iconResolver = ContainerUtil.get<IconResolver<T>>(IconResolver);setIconNode(await iconResolver.resolve(iconProps));};resolve();}, [JSON.stringify(iconProps)]);return (<Fragment>{iconNode}</Fragment>);}
ConfigUtil
Malagu 的应用配置属性是由所有依赖的组件的属性合并而成。通过配置属性,我们可以方便地改变框架的默认行为,而不需要修改一行代码。当我们想要获取一个属性值的时候,可以通过 @Value() 声明式获取某个属性值。与 ContainerUtil 存在同样的限制:非 Class 场景不友好。我们通过 configUtil 工具类就能很方便的在非 Class 场景中获取属性值。使用 ConfigUtil 也有一个限制:必须要在应用启动中或者应用启动完成后,方可以使用。
export function Logo(props: NavItemProps) {const { label, icon, ...rest } = ConfigUtil.get('malagu.shell.logo');props = { ...rest, ...props };return (<NavItem size="medium" gap="xsmall" label={label} icon={<Icon icon={icon}/>} hoverIndicator={false} activatable={false} {...props}/>);}
AnnotationUtil
AnnotationUtil.getType 获取目标对象属性或方法中的参数的类型信息,示例代码如下:
AnnotationUtil.getType(target, targetKey, index); // 获取 target 对象中 targetKey 方法的第 index + 1 个参数的类型AnnotationUtil.getType(target, targetKey); // 获取 target 对象中 targetKey 属性的类型
Prioritizeable
根据优先级大小对数组进行同步或异步排序。
Prioritizeable.prioritizeAllSync(this.contextInitializers).map(c => c.value);
getSuperClasses
获取指定类的所有基类。
getOwnMetadata
获取指定类以及所有基类的相关元信息。
Deferred
延迟获取某一对象的包装类。示例代码如下:
const deferred = new Deferred(); // 创建 deferred 对象deferred.resole(value) // 成功时调用deferred.reject(error) // 失败时调用deferred.promise // 获取包装的 promise 对象
RequestMatcher
请求匹配器,支持 url 模式匹配。使用它可以验证当前请求的 url 是否符合某个 url 模式。该类的对象已经注入到 IoC 容器中,无需自己创建,请从容器中获取。
PathResolver
路径解析器。使用它可以把多个路径片段拼接到一起,它会帮您处理片段之间的 / 问题,以及适当的情况下,自动附加上应用路由前缀。该类的对象已经注入到 IoC 容器中,无需自己创建,请从容器中获取。
