Start the APF Refactoring Tool and choose one of the following options:
Once an option is selected, start it by pressing the Analyze button. The tool will then read the source code, analyze and modify it accordingly to the rules that set setup for each option.
The Nested Child Tables option is the only option that will only result in listing object that needs some attention, not providing any further help from the tool itself.
The remaining options will all alter the source code and write the changes into a new location, <AnalyzeDir>.modified, keeping the original files untouched. This is done in to get the possibility being able to compare the original and altered files with each other.
Once the result is verified, press the Merge button. That will...
After compiling the contents in <AnalyzeDir>.merged and verifying that the business logic works as expected, simply...
If you are using versioning control like e.g. SVN, the result will behaving a folder (<AnalyzeDir>) that contains both original & altered files ready to be checked in.
When chosen, press the analyze button and wait for the result. If you have any nested child tables listed, they will all be listed and you will need to manually refactor those by following the guideline listed in the tool.
Re run the analyze until you have no more nested child tables listed.
This option replaces the source code that might have anything to do with navigation logic, that navigates to a window or uses the window name for comparing purposes in some way.
The result will be having source code using a known window name to be
enriched appending the method Pal.GetActiveInstanceName.
It's purpose is to create a "Dispatch" logic that
navigates to either original windows or customized windows, all depending on the
environment the code is compiled in.
In most cases, having windows that are not customized, the
returned value will be the same window name that is passed as argument:
Pal.GetActiveInstanceName("frmBasePartCharacteristic")
-> frmBasePartCharacteristic
But for customized windows, the returned value will be the name of the
customized window (or simple the name of the window that "replaces" the original
window).
Pal.GetActiveInstanceName("frmBasePartCharacteristic")
-> frmBasePartCharacteristic_Cust
SessionNavigate("frmBasePartCharacteristic");
Example: Before the change
SessionNavigate(Pal.GetActiveInstanceName("frmBasePartCharacteristic"));
Example: After the change
All framework methods that somehow navigates to or opens a window have the
Pal.GetActiveInstanceName logic "built-in" meaning that if
Pal.GetActiveInstanceName would be missed somewhere, the customized window
will still be opened and the "Dispatching" would work just as expected.
The example above, using SessionNavigate which is a framework method,
would still work even if the Pal.GetActiveInstanceName would be excluded
since the SessionNavigate method itself have the
Pal.GetActiveInstanceName method "built-in".
Places where the method is not "build-in" can be e.g. when variables are compared with static window names like here:
if (sName == "frmBasePartCharacteristic")
The above example will return the wrong result if frmBasePartCharacteristic is customized and sName expects to contain frmBasePartCharacteristic_Cust, hence the correct way of solving this is:
if (sName == Pal.GetActiveInstanceName("frmBasePartCharacteristic"))
As result of the different scenarios and not being forced to keep track knowing
when to use Pal.GetActiveInstanceName and when not, the recommendation is
to enrich all possible "navigation" candidates, even if most of them will work
without being enriched. Therefore, the source code might become unnecessary
enriched with Pal.GetActiveInstanceName, but will on the other have be
well defined explicitly indicating when the "Dispatching" might occur.
This option changes the source code that instantiates/opens modal dialogs, typically by changing the implementation of the static method ModalDialog that is part of the dialog template.
The static method ModalDialog will have its implementation altered and use the framework method DialogFactory.CreateInstance, which purpose is to instantiates the proper dialog (original or customized one).
The constructor will have its arguments removed, becoming a default constructor (one without arguments). The parameters to the dialog will instead be set inside the ModalDialog method.
The constructor will become protected, only to be used for sub classing.
public dlgCopyLibrary(SalWindowHandle hWndSource, SalString sSource, SalString sSourcePrompt, SalString sPrompts) { // Assign global reference. App.dlgCopyLibrary = this; // Window Parameters initialization. this.hWndSource = hWndSource; this.sSource = sSource; this.sSourcePrompt = sSourcePrompt; this.sPrompts = sPrompts; // This call is required by the Windows Form Designer. InitializeComponent(); } public static SalNumber ModalDialog(Control owner, SalWindowHandle hWndSource, SalString sSource, SalString sSourcePrompt, SalString sPrompts) { dlgCopyLibrary dlg = new dlgCopyLibrary(hWndSource, sSource, sSourcePrompt, sPrompts); SalNumber ret = dlg.ShowDialog(owner); return ret; }
Example: Constructor and ModalDialog implementation before the change
protected dlgCopyLibrary() { // Assign global reference. App.dlgCopyLibrary = this; // This call is required by the Windows Form Designer. InitializeComponent(); } public static SalNumber ModalDialog(Control owner, SalWindowHandle hWndSource, SalString sSource, SalString sSourcePrompt, SalString sPrompts) { dlgCopyLibrary dlg = DialogFactory.CreateInstance<dlgCopyLibrary>(); dlg.hWndSource = hWndSource; dlg.sSource = sSource; dlg.sSourcePrompt = sSourcePrompt; dlg.sPrompts = sPrompts; SalNumber ret = dlg.ShowDialog(owner); return ret; }
Example: Constructor and ModalDialog implementation after the change
There might be code constructions the tool can't automatically resolve and
that might be in need of manual changes.
Following list shows a list of error messages and how to best proceed with
these.
Error or the Information message | Resolution |
---|---|
Static method 'ModalDialog' could not be found | A modal dialog needs a static ModalDialog method
in order to be properly opened. Add the method ModalDialog. |
Static method 'ModalDialog' found (overload) | The tool can only refactor standard dialogs, which
contains only one static method ModalDialog. Change all the static methods ModalDialog . |
The contents of the static method 'ModalDialog' could not recognized | The static method ModalDialog was found but uses
a unknown pattern. Change the static method ModalDialog. |
A constructor could not be found | There is no constructor. Add the default constructor. |
x constructors found (overload) | There are several constructors. Ensure there is only a default constructor by removing the ones having arguments, keeping the one without any arguments. |
The access modifier for the constructor could not be resolved | A critical error in the tool not being able to resolve
the access modifier for the constructor. Change the access modifier |
Unsupported dialog access, using '<Dialog>.CreateWindow', making the dialog 'Modeless' | This method opens the dialog in a modeless state, not
supported inside IEE. Rewrite the code using <Dialog>.ModalDialog instead. |
Unsupported way of dynamically opening modal dialogs using 'Sal.CompaileAndEvaluate' | Sal.CompileAndEvaluate is unsupported and not to
be used. Rewrite the code using a strongly typed call (<Dialog>.ModalDialog) or using a dynamic call (DialogFactory.DynamicModalDialog) for opening the dialog |
Unsupported dialog, being 'Modeless' | Unsupported window decoration
FndWindowRegistrationFlags.ModelessDialog Rewrite the dialog being a modal dialog |
All opening of modal dialogs must be done via the static mehod(s)
ModalDialog, since these method(s) implements the framework "Dispatching"
using the DialogFactory.CreateInstance method.
If a component do not have a reference to the assembly which owns the dialog but
still needs to open it (probably due to being dynamically installed), the proper
way of opening these dialogs is to use the dynamic method SessionModalDialog
(details).
Note: Older constructions using
Sal.CompileAndEvaluate
and
Ifs.Fnd.ApplicationForms.Var.g_DlgReturnValues
are no longer supported and must be refactored. See
details.
This option changes the source code and makes object accessible in sub classed windows by changing their access modifiers and letting methods become virtual, possible to override.
Items/Methods being private till becomes protected. Normal methods becomes virtual methods.
The change of methods, making them virtual, is not done for all methods. System methods like InitializeComponent & Dispose etc are typically excluded. Late bound methods are excluded also since they already have a public virtual wrapper method, vrt<Method>, that is supposed to be used when overriding these.
This option is cleaning up unnecessary source code like obsolete methods that are not used anywhere. Known source constructions can also be refactored by this option, becoming shorter, easier to read or simply using an alternative API. The step is optional and will not have any logical impact on the business logic if or not run.
Clean Up Action | Comment |
---|---|
Static method 'CreateWindow' removed | The method is not to be used, due to not working together with the IEE design and concepts. Windows should typically be opened using e.g. SessionNavigate, dialogs using e.g. SessionModalDialog. |
Window decoration 'FndWindowRegistration' made shorter | FndWindowRegistration decorations are often unnecessary long, using default parameters that can be removed by using one of its overloaded decorations. |
Window decoration 'FndWindowRegistration' removed | FndWindowRegistration decoration being empty can be removed. |
Window decoration 'FndWindowRegistration' duplicate | FndWindowRegistration decoration being a duplicate can be removed. |
Window decoration 'DynamicTabPage' made shorter | DynamicTabPage decorations are often unnecessary long, using default parameters that can be removed by using one of its overloaded decorations. |
Window decoration 'DynamicTabPage' duplicate | DynamicTabPage decoration being a duplicate can be removed. |
Ctor of App reference removed | "ThreadStatic" references in App.cs files are no longer used. The Constructor needs to have its reference assignment removed. |
Dispose of App reference removed | "ThreadStatic" references in App.cs files are no longer used. The Dispose method needs to have its reference unassignment removed. |
Reference to 'App.cs' removed | "ThreadStatic" references in App.cs files are no longer used. The *.csproj file can exclude its reference. |
Attribute 'NodeSetup' removed | cTreeListBox attribute NodeSetup is unused and can be removed. When used with the .NET 4.5.2 Designers, the old binary serialization causes errors. |
This option highlights areas that need to be redesigned in the application where the current design does not support extending.
Redesign Action | Comment |
---|---|
Use of TableLayoutPanel control | Shows where TableLayoutPanel control is used. TableLayoutPanel control should not be used in a form that is expected to be customized since it does not support visual inheritance. |
This option will change the .NET version for project files, targeting .Net verions 4.5.2, which is the base requirement for Apps 9.
File Action | Comment |
---|---|
Solution File Upgraded | The *.sln file is updated according to the updated template |
navigator-functional.xml Upgraded: Illegal escape combinations replaced | .Net 4.5.2 has been more strict regarding characters that may be included in URL's not being escaped. Some older xml data must be converted to fit the updated rules. |
Project File Upgraded: Item <AddPrefer32Bit> added | Project attribute AddPrefer32Bit is added and set to "false" |
Project File Upgraded: ToolsVersion | Project attribute ToolsVersion is changed from "4.0" to "12.0" |
Project File Upgraded: TargetFrameworkVersion | Project attribute TargetFrameworkVersion is changed from "v4.0" to "v4.5.2" |
Project File Cleaned: ReferenceInclude | Project attribute ReferenceInclude is cleaned
having its specific version/culture child attributes etc removed. Child attribute <HintPath> is added (if needed) Child attribute <Private> is set to <false>, not performing a "Copy Local" operation after compilations. (Slightly improves the build performance due to not having to copy files). |