Introduction
An arbitrary data type in any assembly (.NET DLL) can be instantiated (created), explored (what fields are there), and modified by the user (as long as the user meets the security criteria of the assembly provider).
This article will provide an insight into how Reflection could be helpful in developing generic desktop user control interfaces. It will walk you through creating a generic Windows Form which will accept user input for any arbitrary object.
Background
The power of Reflection lies with the creativity of a developer. Reflection has proven to be useful in many frameworks in Java and .NET based languages. However, we should understand the performance implications of using Reflection in our applications. A good article to read on performance implications in .NET is by Joel Pobar. As more projects are using Service Oriented Architecture (where atomic functionality and stateless operation is key for a successful service offering) in their business solutions, it has increased the amount of test cases needed for quality control. For a practical example of using this control in an application, see SoapPanda (a SOAP client to test Web Services). I guess this much philosophy is good enough on the subject… let's look in to the control code.
How to use this control
The application starts with a demo form. You will browse and select an assembly .NET DLL of your choice or one provided with this code sample.
You can select a data type of the assembly from the list box, and click “Create”. It will create an instance of the data type and an object form for you to edit its fields.
As with any dialog form, you will make modifications and save them by clicking OK. You can click Edit to verify your changes are still in the application.
Alternatively, you can select a data type of the assembly from the list box and click “Create Array”. You can create multiple objects of the selected type and add them in the list. You can click “Edit Array” to modify this list from the demo form.
Code and design
There are two main User Control classes (ComplexType
and ComplexTypeArray
) which are provide bulk of the features for the generic object edit control. Let’s begin with exploring the constructor of ComplexType
.
public ComplexType(Assembly assembly, Object instance, Control parent, bool bProperty)
{
this.parent = parent;
this.instance = instance;
this.clientAssembly = assembly;
this.isProperty = bProperty;
InitializeComponent();
if(isProperty)
AddPropertyControls(this.instance.GetType(), this.panel1);
else
AddFieldControls(this.instance.GetType(), this.panel1);
}
The main design difficulty I had to overcome was allowing any number of objects and the depth of an object within the objects being expanded and collapsed to any extent as long as we have the definition in the assembly (.NET DLL). In my example code, you will notice that I have an Employee
data type referencing its own type, making it a good example of expanding the control to any depth.
You will notice that the two main functions are called AddPropertyControl
and AddFieldControl
. As the names suggest, the fields can be public and private member variables of the datatype, whereas the property is mostly public.
public void AddFieldControls(Type moduleType, Panel panl)
{
FieldInfo[] fields = moduleType.GetFields(BindingFlags.Instance |
BindingFlags.Public | BindingFlags.NonPublic);
if (IsBasicType(moduleType))
{
}else{
foreach (FieldInfo fieldInfo in fields)
{
}
}
}