Seeing the title, most of them say "Creating Objects at runtime" is not a pediatrics, just like this:
DIM newbutton as button = new button ()
NewButton.name = "Button1"
This is indeed created a button at runtime. However, if you need to create a button according to the user, how to do the check box or radio box, it seems to be good:
Dim NewControl As Control
SELECT CASE USERSELECTION
Case "button"
NewControl = New Button ()
Case "checkbox"
NewControl = New Checkbox ()
....
End SELECT
If the user needs dozens of controls inside Windows.Forms, do you want to write doors? Of course, I don't want to do this kind of user, but the demand is always a variety of diverse. If there is a way to specify the type of creation of the object at runtime, even the string of the name of the name is created. Object, how easy it is. The reflection mechanism of .NET FRAMWORK has brought us a solution to the problem. Here, if you only need to create a general object, we can implement it via System.Activator, and more complicated we can implement the constructor.
Reflection reflection is an important mechanism in .NET, many people have already introduced the reflection, let's simply review it. By reflex, you can get a member of each type (including class, structure, delegate, interface, enumeration) in runtime, including methods, properties, events, and constructor, etc., you can also get the name of each member. Limits and parameters, etc. With the reflection, you can make each type of refer to each type. If you get the information of the constructor, you can create objects directly, even if the type of this object is not known when compiling.
Before working on the task of creating a control, let's take a simple example, build a Windows program called VBAppliction, add a new file, enter a new class:
Public class myclasstest
Private Myfield As String
Public Sub New ()
Myfield = "hi!"
End Sub
Public Sub Hello ()
Console.writeline (Myfield)
End Sub
END CLASS
Then add it to the form into a new button, enter the following event code:
'method one
DIM T as type = gettype (myclasstest)
o = system.activator.createInstance (T)
O.hello ()
The first line getType (MyClassTest) function has obtained the type object of the class we created (using the TypeOf function in C #). Next, we use a static method createInstance of the System.Activator class CreateInstance to create an object instance and assign the object reference to O. Activator is a tool for creating a local or remote object. Run this program, we can see the result of the WriteLine function run from the Commond Window from the COMMOND WINDOW. You can see the correctly established object.
If we use the class with a complicated constructor, you can also use the constructor to create the required object, the code is as follows:
'Method Two
DIM T as type = gettype (myclasstest) DIM C as system.reflection.constructorinfo
DIM TYPES () As Type
Redim Types (-1)
c = T.getConstructor (Reflection.BindingFlags.instance_
Or Reflection.BindingFlags.public, _
Nothing, reflection.callingconventions.hasthis, types, nothing
DIM params () as Object
REDIM params (-1)
o = c.invoke (params)
O.hello ()
Here we create an object of System.Reflection.ConstructorInfo, which can obtain information about the class constructor. We use the GetConstructor method of the Type class to search for the available constructor.
What needs to be explained is a Types () array, this array is the parameter type table used by the search constructor. Our constructor has no parameters, so you need an array that is empty but not for Nothing (NULL in C #). Redim types (-1) is the statement to establish this array, written in C #:
Types = New Type [0];
If the construction method is like this:
Public Sub New (BYVAL A AS Integer, B AS String)
Then the corresponding Types array should be
DIM TYPES (1) as Type
Types (0) = getType (int32)
Types (1) = getType (String)
Reflection.bindingFlags.instance and Reflection.BindingFlags.public are a bit shield, which is an option to specify a search.
The params () array is the parameter content table of the constructor, which is the same because there is no parameters, we use the redim -1 syntax.
The Invoke method performs a constructor and creates an object instance.
Now we return to the first implementation method, change the code, will
DIM T as type = gettype (myclasstest)
Change to
DIM T as type = type.gettype ("vbapplication.myclasstest")
The result of run has not changed, this is to say that we have implemented an object from a string! However, the use of the GetType method is limited, and let's talk about us. Now we can realize our desire: dynamically create controls. Through the above knowledge, we easily write a subroutine that dynamically creates a window control:
Private Function CreateNewControls (ByVal targetControls As Control.ControlCollection, ByVal ctlName As String, ByVal ctlType As Type, ByVal ctlSize As Drawing.Size, ByVal ctlLocation As Drawing.Point) As Control
DIM TOCREATE AS Control
TOCREATE = ctype (system.activator.createinstance (ctltype), control)
TOCREATE.NAME = CTLNAME
TOCREATE.SIZE = CTLSIZE
TOCREATE.LOCATION = CTLOCATION
TargetControls.Add (Tocreate)
Return Tocreate
END FUNCTION
The longer statement contains all the contents in the previous example. If you write with C #, you can write it.
TOCREATE = (Control) System.activator.createInstance (CTLTYPE);
We change the event process of the button:
DIM C As Control = Me.createNewControls1 (Me.Controls, "Control1", Gettype (Checkbox), New Size (168, 40), New Point (64, 176))
C.Text = "New Creation"
Now, click the button to see a new Checkbox appear on the window, the title is New Creation, and if the event process is written, you can add an event response for the new control.
It seems that everything is achieved? Note that getType (Checkbox) or the literal representation of the class name, cannot reach the function of creation of objects with strings. If we change this to Type.gettype ("System.Windows.Forms.Checkbox") Well, test, huh, huh, I have fallen. Why is this this? The Type.getType () method is limited to the type of strings or types in the Corlib or the types of the project. If it is from the external assembly, you need to add the name of the assembly. The Windows.Forms assembly is a public assembly, which is located in the program set cache, which can be implemented inside the .NET FRAMWORK. Side by Side execution. So this assembly has a different version. In order to determine the version of the version, we must not only provide the name of the assembly, but also provide the version and strong name of the assembly. According to this idea, on the .NET Framework 1.1, write this sentence into type.gettype ("System.Windows.Forms.Checkbox, System.Windows.Forms, Version = 1.0.5000.0, Culture = neutral, publickeyToken = B
77A
5C
561934E089 "). There is no problem now. The problem is how we get the version and strong name of the Windows.Forms assembly used? You can use the syntax of gettype (checkbox) .AssemblyqualifiedName, we can get this information, we can This information is used for any other control because they all come from the same version of the Windows.Forms assembly. You can now play a fun, put a text box to the window, such as called TextBox1, change the button's event process to:
Try
DIM C As Control = Me.createNewControls1 (Me.Controls, "Control1", Type.GetType ("System.Windows.Forms." & TextBox1.text & ", System.Windows.Forms, Version = 1.0.5000.0, Culture = neutral, publickeytoke = b
77A
5C
561934E089 "), New Size (168, 40), New Point (64, 176))
C.Text = "New Creation" Catch EX AS EXCEPTION
MSGBOX (ex.Message)
END TRY
Now as long as you type "button" in TextBox, press the button, a new button is generated! If you entered Checkbox, a check box will be generated. No matter how hard is the user, the control can "create" on demand ". The reflective mechanism has many uses in .NET, it is said that functions such as class references and virtual constructors in delphi.net are used for .NET FRAMWORK is achieved by means of reflection and system.Type types, making this tool will give Your program has a lot of color.