To Enable a Graph Extension Conditionally (IsActive)
You need to disable a graph extension when it is not required by the system logic (for example, when the feature that uses the extension is not enabled) because when an extension is constantly active, it can impair the system's performance. You can also disable a graph extension for a specific derived graph.
To disable or enable a graph extension depending on a condition, you need to implement the public static bool IsActive method in the extension. The following code shows an example of the implementation of the IsActive method.
public static bool IsActive()
{
return PXAccess.FeatureInstalled<FeaturesSet.rutRotDeduction>();
}
In the code above, the extension is enabled when the rutRotDeduction feature is enabled.
If the IsActive method returns false for an extension, this extension is not loaded. This means the following:
- Form controls bound to views defined in that graph extension are automatically hidden.
- Event handlers implemented in the graph extension are ignored. Overridden event handlers and methods with the PXOverride attribute are also ignored.
- Views defined in the graph extension will not be available.
Disabling a Graph Extension for a Derived Graph
The graph extension applies not only to the graph specified in the graph extension’s declaration but also to all graphs derived from the graph specified in the graph extension’s declaration.
- A base graph, ARInvoiceEntry
- Two graphs, SOInvoiceEntry and ARSpecificInvoiceEntry, which are derived from ARInvoiceEntry
- A graph extension, ARInvoiceEntryAdvanceTaxesExt, that has been declared for ARInvoiceEntry
In this example, MYOB Acumatica Framework applies the members declared in the ARInvoiceEntryAdvanceTaxesExt graph extension to all of the following graphs: ARInvoiceEntry, ARSpecificInvoiceEntry, and SOInvoiceEntry.
The IsActive method in a graph extension controls whether the graph extension is enabled and applied to the graph specified in the graph extension’s declaration and all of the graph’s inheritors. In the current example, if the IsActive method is declared in ARInvoiceEntryAdvanceTaxesExt and returns false, then the ARInvoiceEntryAdvanceTaxesExt graph extension is disabled for all of the following graphs: ARInvoiceEntry, ARSpecificInvoiceEntry, and SOInvoiceEntry.
- Disable a graph extension for a specific graph inheritor. For example, you may not want to apply logic from the ARInvoiceEntryAdvanceTaxesExt graph extension to the SOInvoiceEntry graph.
- Disable a graph extension for all derived graphs. For example, you may need the ARInvoiceEntryAdvanceTaxesExt graph extension to be applied to only the ARInvoiceEntry graph.
public static bool IsActiveForGraph<Graph>()
Inside the method, you need to check the type of the graph to which the extension is applied by using the TGraph generic type argument.
- Disabling the graph extension for a specific graph inheritor: If you do not want to
apply the logic from ARInvoiceEntryAdvanceTaxesExt to
SOInvoiceEntry, for example, the implementation of the
IsActiveForGraph method should be coded as
follows.
public static bool IsActiveForGraph<TGraph>() => typeof(TGraph) != typeof(SOInvoiceEntry);
- Disabling a graph extension for all derived graphs: If you want the
ARInvoiceEntryAdvanceTaxesExt graph extension to be applied to only
the ARInvoiceEntry graph, for example, the implementation of the
IsActiveForGraph method should be coded as
follows.
public static bool IsActiveForGraph<TGraph>() => typeof(TGraph) == typeof(ARInvoiceEntry);
The full code of the ARInvoiceEntryExt graph extension in this example should look as follows.
public class ARInvoiceEntryExt : PXGraphExtension<ARInvoiceEntry>
{
public static bool IsActive()
{
return PXAccess.FeatureInstalled<FeaturesSet.retainage>();
}
public static bool IsActiveForGraph<TGraph>()
where Graph : PXGraph // Constraint is not obligatory
{
// Check the type of the graph here
return typeof(TGraph) == typeof(ARInvoiceEntry);
}
}
Disabling a Generic Graph Extension
If you have a generic graph extension and graph extensions derived from this generic graph extension, to disable them, you need to implement the IsActive method in each of the derived graph extensions.
For example, suppose you have a generic graph extension declared as shown the following code.
public class GraphExtBase<TGraph, TDac> :
PXGraphExtension<TGraph>
where TGraph : PXGraph
where TDac : class, IBqlTable
{ }
The derived graph extension looks as the following code shows.
public class GraphExtAPInvoice :
GraphExtBase<APInvoiceEntry, APInvoice>{}
To disable the GraphExtAPInvoice
graph extension, you need to implement
the IsActive method as the following code shows.
public class GraphExtAPInvoice :
GraphExtBase<APInvoiceEntry, APInvoice>
{
public static bool IsActive()
{
return PXAccess.FeatureInstalled<FeaturesSet.
AdvancedAPInvoice>();
}
}
For details on generic graph extensions, refer to Reusing Business Logic.
Restrictions in the IsActive Method
Inside the IsActive method, you should not create a graph instance because it can lead to deadlocks. If you need to read data from the database, you can use database slots by doing the following:
- In a graph extension where you need to define the IsActive method, you also define a database slot that depends on a DAC from which you need to read data. In the slot, you cache data that you need to access.
- In the IsActive method, you access the data from the slot.
For example, suppose that you need to enable the extension in the
IsActive method only if the InspectionEnabled
property
of SOSetup
DAC is true. The following code shows how you can access the
InspectionEnabled
property by using a database slot.
private class SOSetupInspection : IPrefetchable
{
public static bool InspectionEnabled =>
PXDatabase.GetSlot<SOSetupInspection>("SOSetupInspection", typeof(SOSetup))._inspectionEnabled;
private bool _inspectionEnabled;
void IPrefetchable.Prefetch()
{
using (PXDataRecord soSetup =
PXDatabase.SelectSingle<SOSetup>(new PXDataField<SOSetup.inspectionEnabled>()))
if (soSetup != null) _inspectionEnabled = (bool)soSetup.GetBoolean(0);
}
}
public static bool IsActive() => SOSetupInspection.InspectionEnabled;
In the code above, you do the following:
- In the extension, you define the
SOSetupInspection
database slot which depends on theSOSetup
table. In the slot, you cache theSOSetup.InspectionEnabled
value. - In the IsActive method, you check the
SOSetupInspection.InspecionEnabled
property which holds the cached value of theSOSetup.InspectionEnabled
property.
For more information on database slots, see Use of Slots to Cache Data Objects.