In the vast majority of times when we are coding an application, we use the
" to instantiate an object, as shown below:
Dim obj As New AnyObject
In this article we will see two other ways on how to
<code>dynamically instantiate objects without using the keyword "
In a project that I recently participated one of the requirements was to instantiate objects dynamically based
System.Types external to the application.
It was a
<span class="hps">UserControl</span> whose purpose was to display in a
<span class="hps">PropertyGrid</span> properties of the instantiated object so that only the properties modified by the user in the PropertyGrid, were persisted and subsequently reapplied to the object whenever a new instance of it was created.
System.Type to be loaded was provided by the user by informing the
assembly location on disk and the
System.Type to instantiate.
During the tests phase, I've used other assemblies created by me in other projects and also assemblies created by others to make sure it was actually working properly regardless of the class.
During this period, I found some situations in which the instantiation via reflection would not work.
Instantiating through reflection
This type of instantiation is widely used by most programmers who need to dynamically create instances of System.Type 's external to the application.
Assembly.CreateInstance(string) to instantiate a type all the instantiation process occurs normally as if you were using the keyword "
new", that is the constructor of the class is executed and all its fields gets initialized properly.
Dim obj1 As Object = _assembly.CreateInstance("MyExternalAssembly.AnyObject")
In the example above we are instantiating a class called "
AnyObject" on the assembly called "
In this case you must provide a string with the full name of the
including the assembly name and namespace (if any), and the name of the class also it must exist in
<span class="hps alt-edited">the</span> <span class="hps alt-edited"></span> <span class="hps alt-edited"></span> <span class="hps alt-edited">_assembly </span>object, otherwise the instantiation does not occur.
Note: Internally after check if the provided
System.Type string exists in the loaded
assembly, it runs the
<span class="hps">Activator.CreateInstance</span><span class="hps atn">(</span><span>System.Type)</span>
method that returns the instance to the caller.
Instantiating through Serialization/Deserialization
I decided tocall this kind of instantiation as "serialization / deserialization" due to the fact that its being used internally in the .Net Framework to deserialize
<span class="hps">WCF</span> <span class="hps">DataContracts</span>.
For a few times during the testing phase in the project I participated in, I came across situations where logic in the constructor of the class were preventing the instantiation of the object, especially when it was a commercial component whose licensing mechanisms were located in the constructors of the class and were firing exceptions when licensing rules were violated.
Note: In my opinion a good mechanism for licensing and validation must rely not only on the constructor of a class, but also in key methods of the class, and other classes internal to it.
In cases like this instantiating a class by using Reflection is not possible since via Reflection and also through the
<span class="hps">keyword</span> "
new", the constructor always runs during instantiation, preventing it from complete.
By analyzing the .Net framework code through Reflector, I found that the
<span class="hps">WCF's </span>DataContracts when deserializing an object were never invoking any class's constructors, as well as their fields were not initialized with "default" values that eventually were defined on it.
The reason why the fields are not initialized makes sense. From what I understand is a way to gain performance, since during deserialization - after object creation - these fields will receive different values other than the "Defaults", that way it doesn't make any sense if they were assigned twice, once with their "default" values ??and another with the values ??of serialization.
I still do not understand why the constructor is not invoked, perhaps for performance reasons as well? I do not know ...
Below is the code that does the instantiation without running the constructors or initializing fields:
Dim type = _assembly.GetType("MyExternalAssembly.OtherObject")
Dim obj1 As Object = System.Runtime.Serialization.FormatterServices.GetUninitializedObject(type)
Note that the method
<span class="hps">GetUninitializedObject</span><span class="hps">()</span> takes a
System.Type that can be a
System.Type from an existing class in the assembly itself or an external assembly, however the external assembly should be previously loaded.
In the example above we use a
System.Type from an assembly external to the application, whose constructor throws an
InvalidOperationException, therefore we can never instantiate an object of this class if we use the standard instantiation by using the keyword "new" or a instantiation via Reflection
Using the source code
In the solution of the source code of this article there are two projects, a
<span class="hps">Class Library</span> and a
<span class="hps">Windows Form</span> <span class="hps">Application</span>.
The "MyExternalAssembly" is a
Class Library which has two classes, one is a class called "AnyObject" that allows any instantiation mentioned in this article to be used, the other class is called "otherObject" which is a class whose default constructor fires one exception, therefore it can be instantiated only by using the process "serialization/deserialization" presented here.
<span class="hps">PropertyInspector</span> is a
<span class="hps">Windows Forms</span> <span class="hps">Application</span> that allows you to select an external assembly - in this case the assembly MyExternalAssembly - and display your fields in a PropertyGrid, as follows:
The purpose of this article is to show to beginners alternative ways to instantiate objects and not neither to elect the best way to instantiate an object nor the one that is "more correct".
Perhaps there are other ways to instantiate objects in .NET I may not know yet, if you do, please, feel free to share it with us by using the session "Comments and Discussions".
Depending on usage, one method may be more advantageous than the other in terms of gains in performance, usability, etc.