【发布时间】:2021-06-04 00:27:08
【问题描述】:
假设我通过创建一个包装它的新 TS 类来扩展 CRM FormContext,并添加辅助函数。这个新的ExtendedContext 具有类似getDisplayValue(attName) 的函数,它获取属性,处理不在表单上的属性,确定属性类型,并适当地返回“显示的值”是什么。随着我添加更多辅助函数,类变得越来越大,这意味着我需要开始将类拆分为更多类,但我不希望 API 发生变化。消费代码不必知道它需要创建一个DisplayExtendedContext 类来调用getDisplayValue,所有函数都应该存在于主扩展上下文中。推荐的方法是什么?
我目前的方法感觉不对,看起来像这样:
// extendedContex.ts
import { DisplayContext } from "../context/display";
export class ExtendedContext implements XrmExt.ExtendedContext {
public context: Xrm.FormContext // Actual Xrm.Client form context
private display: DisplayContext;
constructor(context: Xrm.FormContext){
this.context = context;
this.display = new DisplayContext(this);
}
public getDisplayValue(att: string): string {
return display.getDisplayValue(att);
}
}
// xrmExt.d.ts
declare namespace XrmExt {
interface ExtendedContext {
getDisplayValue(att: string): string;
}
}
// ../context/display.ts
export class DisplayContext {
private context: XrmExt.ExtendedContext;
constructor(context: XrmExt.ExtendedContext){
this.context = context;
}
public getDisplayValue(att: string): string {
// Do logic here, with full access to the ExtendedContext
}
}
以下是它存在的问题:
- 我必须复制
ExtendedContext函数的传递。所以我添加的每个函数,我都必须在较小的上下文类中实现它,然后将它作为传递添加到ExtendedContext类和ExtendedContext接口中。我很懒,我不想对每个函数都这样做。 - 这个比较小,但是传递给
DisplayContext的ExtendedContext没有完全初始化,这可能会导致空引用错误。例如,如果DisplayContext在其自身实现的构造函数中调用XrmExt.ExtendedContext接口上的函数,则不会填充ExtendedContext类的类级别“显示”字段,并且会出现空引用异常被抛出。永远不要从较小类之一的构造函数访问ExendedContext的“不言而喻”的规则将防止这成为问题。 我猜混合可能是前进的方向,但我不确定。想法/建议?
【问题讨论】:
-
那么……继承? (如果没有,为什么不呢?)
-
我需要多重继承。我将有多个应该组合成 API 的类。我想我可以链式继承,但这有点奇怪......
-
与仅在需要的地方导入帮助程序相比,这种方法是否有优势 - 在调用时传入 formContext ?这将支持摇树。您可以导入整个模块以获得对可用功能的智能感知支持。是因为您在扩展上下文中维护了一些状态 - 这意味着您需要创建一个实例?在您的代码片段中 - 唯一的状态是 DisplayContext - 这是否保持状态?
-
在某些情况下可能存在某种状态,但大多数情况下没有。我不传递表单上下文的主要原因是因为将它传递给每个函数调用会很烦人。拥有非静态的东西确实更容易测试。
-
嗨 Daryl,我还没有学习 TS,但在 C# 中我会使用
partial类声明。 TS有这些吗?例如,在 C# 中,我经常在单独的文件中使用额外的partial声明来扩展代理类。例如,我会将一般功能放在Contact+.cs的partial声明文件中。如果我有该代理类的特定功能,我可能会添加Contact+Email.cs、Contact+Merge.cs和Contact+Hierarchy.cs,每个都包含相关成员的partial声明。