Introduction
The protected keyword in C# allows access to its properties and methods from within the class and derived classes. You would set public properties to allow access from other functions. This is standard practice to force use of specific functions and properties that should be used and prevent internal methods from being called.
Typically in Acumatica, we have public methods that can be called from other graphs that require sending a cache, or having an object sent as a parameter to perform one or many actions on. A typical protected method in a graph is something that is called on the current object that is set. For example, SOShipmentEntry has a protected function SyncShipDateWithLinks. This goes through the current shipment record in cache and updates the ship date on the linked SOOrderShipment record. This function should not be called outside of the graph, which is why it is marked as protected.
Graph Extensions
When doing a graph extension, we may need to access, or even override these properties and methods. It would be within the same graph, so using these protected methods would use logical sense. The problem is that you are not able to access them through the Base of the extension, because they are protected. This is where PXProtectedAccess comes into play.
The first example would be accessing a protected property on the SOOrderEntry screen. I have a process that will trigger off a custom CopyOrder command. This property has a public get, but a protected set. The only place that this property is set is during the CopyOrder action.
There are two ways to go about accessing the property.
The first way would be to create an abstract protected access graph extension, and declare the protected properties as abstract and as public. This would override the scope of the initial graph. From there, you would extend that graph, and be able to use the property.
GIST: https://gist.github.com/kjrichardson/698684c2c1806fdd437abb7dd457627a
As you can see, we are extending both the main graph and the extension. Base1 would call the extension, which has the IsCopyOrder setter set to public. This would allow us to run our custom copy order function without having to call the action that sets that property from the SOOrderEntry graph.
The other way we could accomplish this would be with one class. We would perform all of the code in a single abstract class. Both methods work in the current version of Acumatica.
GIST: https://gist.github.com/kjrichardson/04642c509aa3849b1fafeafd8ecaf56f
Overriding Protected Functions
Next, we will look at overriding a protected function. Normal event handlers allow you to do this without having to use protected access, but sometimes you may need to override additional functionality that is not event driven. One function that I had to override was the LinkPOLineToSOLineSplit function in the POCreate graph. I needed to link information from the sales order to the purchase order line when it was linked. The event handlers for these fields or DACs updating did not get triggered, so overriding the function that set it was the next step. When doing a typical override, you would get the following errors:
To create an override, you must have two functions. The first level extension would have your PXOverride code that would be called. If you stopped here, you would get access failures. The second step would be to create a ProtectedAccess extension that extends both the base graph, as well as the graph extension that has your override.
GIST: https://gist.github.com/kjrichardson/e5e8b7d2656fa66617e0cb301defebe1
Note, the delegate and the method tagged with PXOverride must be set as public. This allows the secondary graph extension to access the overridden function and links it with the protected access.
Summary
Sometimes, hooking into an event using a FieldUpdated, RowUpdated, or another standard event is not enough. Sometimes, the code is baked into protected events. Sometimes this method is beneficial for performance reasons, as you only need to trap the protected event and not run logic every time another field or row is updated. I am glad that Acumatica added this functionality in 2020 R1 and have found many benefits of using it and hope you will too!
Happy Coding!