Suppose I have enhanced the CRM FormContext by creating a new TS class that wraps it and adds helper functions. This new ExtendedContext
includes functions like getDisplayValue(attName)
, which retrieves the attribute, handles cases where it's not on the form, identifies the attribute type, and returns the appropriate "displayed value". As I continue to add more helper functions, the class becomes larger and larger, necessitating splitting it into multiple classes. However, I want to avoid changing the API. The consuming code should not be required to create a separate DisplayExtendedContext
class to utilize getDisplayValue
; all functions should remain within the main extended context. What is the best approach to tackle this?
The current approach feels cumbersome and appears as follows:
// 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 {
// Implement logic here, with full access to the ExtendedContext
}
}
Here are the issues encountered:
- I find myself duplicating pass-throughs for
ExtendedContext
functions. For each function added, I must implement it in the smaller context class, include it as a pass-through in theExtendedContext
class, and update theExtendedContext
interface. This repetitive task is tedious, and I seek an alternative solution. - Although minor, the
ExtendedContext
passed to theDisplayContext
is not fully-initialized, potentially leading to null reference errors. If theDisplayContext
were to invoke a function on theXrmExt.ExtendedContext
interface within its constructor that it also implements, the class-level "display" field of theExtendedContext
class may not be populated, resulting in a null reference exception. An unwritten rule of never accessing theExendedContext
from a smaller class constructor could prevent this issue from arising. I am considering Mixings as a possible way forward, but unsure if it's the right direction. Any thoughts or suggestions?