Refactor the code to the end
-- Record a simple code refactoring
The non-modal forms in the system currently developed require the management of the main window. Currently, most of the Code is set each time the form is opened, for example:
FrmParaeter frm = new FrmParameter ();
Frm. MdiParent = Application. OpenForms [0]; // set the mdi window
Frm. show ();
The disadvantage of this approach is:
You need to set the MdiParent of the form each time you open the form. The setting method is the same and cumbersome. In addition, no exception is identified when you set the main form.
One improvement is to provide: rewrite the Show () function in the FrmParaeter form, as shown below:
Public new void Show ()
{
Try
{
This. MdiParent = Application. OpenForms [0]; // set MdiParent
}
Finally
{
Base. Show (); // ensure that the form can still be opened after an exception occurs
}
}
In this way, the form FrmParaeter has the show function in the Main Window Management, instead of setting each time, it can also be opened in case of exceptions.
The above practices focus on public code from the perspective of a single form class Show function call, but this function is also required for other form classes in the system, so you can consider adding the form base class FormMDIChild, extract the public code to the base class. The form managed by the main window is derived from the base class of the form.
Restructuring now seems to be perfect for o (∩ _ ∩) o ..., The Code is as follows:
Type tp = Type. GetType ("xxx. FrmParmeters, xxx ");
If (tp! = Null)
{
Object obj = Activator. CreateInstance (tp, ids, count );
Form frm = obj as Form;
Frm. Show ();
}
Although the basic classes inherited by FrmParmeters have the function of managing the main window, the new Show function hides the Show function of the Form base class. Therefore, the Show function is called using Form, call the Show method of the Form class instead of FormMDIChild. In this case, it is inappropriate to use function overload to hide functions with the same name of the base class. The Improved direction is to overload virtual functions. Generally, the public methods of most APIs are designed to be non-virtual, and some methods that may change are set to Protected Virtual Methods (refer to the template method mode ), the same is true for event design. When a derived class needs to expand the base class, it is preferred to choose the overload virtual method. Therefore, the OnShown method is reloaded in FormMDIChild.
Protected override void OnShown (EventArgs e)
{
Base. OnShown (e );
Try
{
If (Application. OpenForms. Count> 0) this. MdiParent = Application. OpenForms [0];
}
Catch {} // do not handle exceptions
Finally
{
Base. OnShown (e); // make sure you can open
}
}
The above practice is considering setting MdiParent to display the form normally even if an exception occurs. However, it is not a good practice to Catch all exceptions without handling them, if we know how to avoid setting MdiParent without exception, we do not need to use exception handling instead of parameter determination.
When querying msdn and using Reflector to view MdiParent Attribute source code to set MdiParent, exceptions that may be triggered include:
The Form assigned to this attribute is not marked as an MDI container.
-Or-
The Form assigned to this attribute serves as both the child MDI Form and the MDI container Form.
-Or-
The Form assigned to this attribute is located on another thread.
In fact, the current form must be a non-MDI form and a superior form must be an MDI form. Therefore, the code for further modification is as follows:
Protected override void OnShown (EventArgs e)
{
Base. OnShown (e );
If (Application. OpenForms. Count> 0)
{
// The top-level window exists.
Form parent = Application. OpenForms [0];
// If the top-level window is MdiContainer and the current window is not MdiContainer
If (parent. IsMdiContainer &&! This. IsMdiContainer)
{
This. MdiParent = parent;
}
}
}
Although the OnShown function is triggered after the form is displayed, the effect is not affected. Another approach is to place the above Code in the Construction Function of the base class FormMDIChild, which has the same effect and ensures that the code segment is called.
In this way, is it more perfect... You are welcome to give us some advice on further improvement.
Summary:
IsMdiContainer attribute. setting this attribute to true (false by default) indicates that the form is an mdi form. The mdi form is characterized by closing the form and closing its subforms. The MdiParent attribute is used to set the mdi form of the form. The parent form must be an mdi form, but the child form must be a non-mdi form.
Avoid using exception handling as the program logic processing. Before calling an api, you should refer to its possible exception descriptions for pre-judgment.
3. Unless required, do not use the new keyword to reload the methods with the same name as the base class. Using the base class to call Show and the subclass to call the Show method has different effects. This violates the LSP: where any base class can appear, subclass can certainly appear.
4. One of the purposes of refactoring is to centralize public code (method blocks). In This refactoring, the code that sets the mdiparent attribute of the main form is first centralized into the form class, when this function is required for each form, a base class is constructed to extract the method to the base class.