The first step in creating an object using reflection is to obtain a Type object that represents the type you want to instantiate. Once you have a Type instance, call its GetConstructor method to obtain a ConstructorInfo representing one of the type's constructors. The most commonly used overload of the GetConstructor method takes a Type array argument and returns a ConstructorInfo representing the constructor that takes the number, order, and type of arguments specified in the Type array. To obtain a ConstructorInfo representing a parameterless (default) constructor, pass an empty Type array (use the static field Type.EmptyTypes); don't use null, or GetConstructor will throw a System.ArgumentNullException. If GetConstructor can't find a constructor with a signature that matches the specified arguments, it will return null.
Once you have the desired ConstructorInfo, call its Invoke method. You must provide an object array containing the arguments you want to pass to the constructor. Invoke instantiates the new object and returns an object reference to it, which you must cast to the appropriate type. The following code demonstrates how to instantiate a System.Text.StringBuilder object, specifying the initial content for the StringBuilder (a string) and its capacity (an int).
// Obtain the Type for the StringBuilder class. Type type = typeof(System.Text.StringBuilder); // Create a Type[] containing Type instances for each // of the constructor arguments - a string and an int. Type[] argTypes = new Type[] {typeof(System.String), typeof(System.Int32)}; // Obtain the ConstructorInfo object. ConstructorInfo cInfo = type.GetConstructor(argTypes); // Create an object[] containing the constructor arguments. object[] argVals = new object[] {"Some string", 30}; // Create the object and cast it to StringBuilder. StringBuilder sb = (StringBuilder)cInfo.Invoke(argVals);
Reflection functionality is commonly used to implement factories in which you use reflection to instantiate concrete classes that either extend a common base class or implement a common interface. Often both an interface and a common base class are used. The abstract base class implements the interface and any common functionality, and then each concrete implementation extends the base class.
There's no mechanism to formally declare that each concrete class must implement constructors with specific signatures. If you intend third parties to implement concrete classes, your documentation must specify the constructor signature called by your factory. A common approach to avoid this problem is to use a default (empty) constructor and configure the object after instantiation using properties and methods. The following code demonstrates a factory to instantiate objects that implement the IPlugin interface
using System; using System.Reflection; // A common interface that all plug-ins must implement. public interface IPlugin { string Description { get; set; } void Start(); void Stop(); } // An abstract base class from which all plug-ins must derive. public abstract class AbstractPlugin : IPlugin { // Hold a description for the plug-in instance private string description = ""; // Sealed property to get the plug-in description. public string Description { get { return description; } set { description = value; } } // Declare the members of the IPlugin interface as abstract. public abstract void Start(); public abstract void Stop(); } // A simple IPlugin implementation to demonstrate the PluginFactory class. public class SimplePlugin : AbstractPlugin { // Implement Start method. public override void Start() { Console.WriteLine(Description + ": Starting..."); } // Implement Stop method. public override void Stop() { Console.WriteLine(Description + ": Stopping..."); } } // A factory to instantiate instances of IPlugin. public sealed class PluginFactory { public static IPlugin CreatePlugin(string assembly, string pluginName, string description) { // Obtain the Type for the specified plug-in. Type type = Type.GetType(pluginName + ", " + assembly); // Obtain the ConstructorInfo object. ConstructorInfo cInfo = type.GetConstructor(Type.EmptyTypes); // Create the object and cast it to StringBuilder. IPlugin plugin = (IPlugin)cInfo.Invoke(null); // Configure the new IPlugin plugin.Description = description; return plugin; } }
This statement will create an instance of SimplePlugin using the PluginFactory class.
IPlugin plugin = PluginFactory.CreatePlugin( "CreateObjectExample", // Private assembly name "SimplePlugin", // Plug-in class name "A Simple Plugin" // Plug-in instance description );
No comments:
Post a Comment