Extension Classes & the _Extension Pattern in Dynamics 365 Finance & Operations
Question 20 — Adding methods to standard objects the upgrade-safe way with extension classes.
Interview Question
Model Answer (Short)
An extension class lets you add new methods to an existing standard (or third-party) table, class
or form without modifying the base object — the modern replacement for over-layering. You create a
final class decorated with the [ExtensionOf(...)]
attribute pointing to the target, and its name ends with the _Extension suffix.
Methods you add are typically static and behave like extension methods — the first parameter
represents the object being extended (or you use this for table/form extensions). This keeps
customizations upgrade-safe because Microsoft's code is never touched.
Rules of the _Extension Pattern
Core rules
- The extension class must be marked
final. - It must use the
[ExtensionOf(...)]attribute (e.g.tableStr,classStr,formStr) to name the target. - The class name should end with the
_Extensionsuffix. - Extension methods are typically static; for tables/forms the extended instance is available via
this. - Only one extension class per object per model is the recommended practice.
Extension class vs. Chain of Command
- An extension class adds new methods that didn't exist on the base object.
- Chain of Command wraps existing methods to run logic before/after them.
- Both can live in the same
_Extensionclass — new methods plus wrapped (CoC) methods. - Both are upgrade-safe alternatives to over-layering.
Prerequisites (Rule 5)
- Visual Studio with the Dynamics 365 developer tools.
- A custom model / package referencing the package that owns the target object.
- The target object must be extensible (most standard tables/classes are).
Code Example — Adding a method to a standard table
[ExtensionOf(tableStr(DirPersonName))]
final class DirPersonNameAbc_Extension
{
// New static extension method; _person is the extended record
public static PersonName abcFullName(DirPersonName _person)
{
return strFmt('%1 %2 %3',
_person.FirstName,
_person.MiddleName,
_person.LastName);
}
}
Extending a standard class
[ExtensionOf(classStr(SalesLineType))]
final class SalesLineTypeAbc_Extension
{
public static boolean abcIsHighValue(SalesLineType _salesLineType,
Amount _threshold)
{
// Add reusable helper logic to a standard class
return _salesLineType.salesLine().LineAmount >= _threshold;
}
}
New method + CoC wrapper in one extension class
[ExtensionOf(tableStr(SalesTable))]
final class SalesTableAbc_Extension
{
// 1) A brand-new method added to SalesTable
public boolean abcIsBlocked()
{
return this.CustAccount != '' &&
CustTable::find(this.CustAccount).Blocked != CustVendorBlocked::No;
}
// 2) A Chain of Command wrapper on an existing method
public boolean validateWrite()
{
boolean ret = next validateWrite();
if (ret && this.abcIsBlocked())
{
ret = checkFailed("Customer is blocked.");
}
return ret;
}
}
Extension Class vs. Over-layering
| Aspect | Extension Class | Over-layering (legacy) |
|---|---|---|
| Modifies base code | No | Yes |
| Upgrade safety | High — survives updates | Low — conflicts on updates |
| Adds new methods | Yes (via extension methods) | Yes (directly) |
| Recommended status | Current / preferred | Deprecated for customer/partner code |
Points the interviewer wants to hear
- Extension classes add methods without over-layering the base object.
- Must be
final, decorated with[ExtensionOf], and end with_Extension. - Extension methods are typically static; tables/forms expose the instance via
this. - An
_Extensionclass can hold both new methods and CoC wrappers. - Keep to one extension class per object per model.
Likely Follow-up Questions
- Why is over-layering discouraged in favour of extensions?
- What is the difference between adding a method and wrapping one with CoC?
- Why must an extension class be declared
final? - Can you extend a method that is marked
finalorprivateon the base object?
Key Takeaway
Extension classes are the upgrade-safe way to add behaviour to standard objects. Mark the class
final, decorate it with [ExtensionOf], follow the
_Extension naming, and combine new methods with
Chain of Command wrappers — all without ever touching Microsoft's code.