Skip to content

Latest commit

 

History

History
80 lines (59 loc) · 6.06 KB

File metadata and controls

80 lines (59 loc) · 6.06 KB

PX1003

This document describes the PX1003 diagnostic.

Summary

Code Short Description Type Code Fix
PX1003 An instance of the base graph type should be created with the PXGraph.CreateInstance() factory method. Warning Available

Diagnostic Description

The PX1003 diagnostic reports graph instances of the base PXGraph type that are instantiated directly with a graph constructor (for example, new PXGraph()). The PXGraph.CreateInstance<T>() factory method should be used instead to instantiate correctly initialized graph instances from code.

This diagnostic has a complementary rule, PX1001, which reports direct constructor calls for concrete graph types derived from the PXGraph type (for example, new SOOrderEntry()). Both diagnostics share similar reasoning, but they have different severity levels.

Difference between Graph Constructor Calls and PXGraph.CreateInstance Factory Method

During the execution of the PXGraph.CreateInstance factory method, the Acumatica Framework performs a complex initialization of the graph instance, including the following steps:

  • Collection and initialization of graph extensions
  • Dependency injection of services into a graph
  • Loading and unloading of the graph state from the session

These steps are omitted when the graph instance is created via a direct constructor call.

The sections below describe some of the steps that are performed during the graph initialization.

Graph Extensions

The Acumatica Framework relies on a complex extension mechanism to provide customization capabilities. Proper initialization of graph instances is essential for this mechanism to function correctly. Such initialization is implemented in the PXGraph.CreateInstance() factory method via the dynamic generation of a proxy class that derives from the original graph type and integrates all graph extensions into the original graph's logic. Among extension mechanisms that rely on this dynamic code generation are:

  • The PXOverride attribute mechanism
  • The PXProtectedAccess attribute mechanism
  • The overrides of event handlers

Graph constructors will only create instances of the original graph type without any graph extensions loaded for it. This can lead to incorrect and unexpected behavior at runtime.

Dependency Injection

The Acumatica Framework provides its own Dependency Injection (DI) mechanism to inject different services into the graph instance via the property injection pattern. The PXGraph.CreateInstance() factory method ensures that all DI services are correctly injected into the graph instance, while direct constructor calls bypass this mechanism. This means that graphs created via constructors may lack necessary DI services, leading to runtime errors.

Why Warning Severity for Base PXGraph Type

The Acumatica Framework contains graph extensions created for the base PXGraph type. These extensions are applied to all graphs derived from the PXGraph type (essentially every graph in the system). The Acumatica Framework also includes DI services that are injected into the base PXGraph type and expected to be available in all derived graphs. This means that even the instance of the base PXGraph type should be properly initialized to ensure that these extensions and DI services are available.

If you create an instance of the base PXGraph type directly, the initialization of these extensions and DI services will not be performed, which can lead to unexpected behavior. If you need a general graph instance with all initialized extensions and DI services, you can create it by using the following code.

var generalGraphWithAllExtensionsAndDiServices = PXGraph.CreateInstance<PXGraph>();

However, the business logic rarely uses PXGraph instances. Instead, it uses concrete graph types that are derived from PXGraph. Therefore, the direct instantiation of the base PXGraph type is a less critical issue compared to concrete graph types. It is acceptable to instantiate the base PXGraph directly in a single use case scenario: When you need to query data directly from the database. This scenario is described in detail below.

Because of these reasons, the PX1003 diagnostic has the Warning severity instead of Error unlike the PX1001 diagnostic.

Lightweight Data Querying

It is acceptable to directly instantiate the base PXGraph type in the following scenario: When you use the base PXGraph instance created via a direct constructor call only to query data from the database (for example, for some service). Sometimes, Acumatica developers use such "cheaper," not fully initialized graph instances just to retrieve data. In this case, the full graph initialization via CreateInstance is an unnecessary expensive operation, and developers use a cheaper alternative.

If you need to create a lightweight PXGraph instance via direct constructor call for data querying, you should just suppress the PX1003 warning on the constructor call with Acuminator suppression comment. Acuminator is aware of this scenario and will even generate a default justification for such suppressions in this case.

Code Fix Behavior

The code fix replaces the direct call to the PXGraph constructor with the call to the PXGraph.CreateInstance<PXGraph>() factory method.

Example of Incorrect Code

// Warning: Constructor call for the base PXGraph type
var graph = new PXGraph();

Example of Code Fix

// Correct: Use CreateInstance for the base PXGraph type
var graph = PXGraph.CreateInstance<PXGraph>();

Related Articles