Thursday, September 17, 2009

Reflection in .NET

UPDATE (11/20/09): There was a bug of sorts in the MyReflectionClass posted below. It was in the LoadAssembly() method and it’s been corrected, because we really do have to take into account a path to the Assembly.  Sorry for any confusion or pulling of hair that this has caused. =0(

This is probably one of the most asked questions I see: How can I dynamically instantiate a class from a string containing the name of the class? And here is what I always reply to that question:

Reflection is a handy way to not only dynamically load controls, but also to dynamically download server-side components automatically.

Below is a simplified version of a Reflection class (other things could be added to it, for example allowing parameters to be passed).

It's easy to use too. Here's one way to use it:

MyReflectionClass oReflection = new MyReflectionClass(assembly, classname);
string message = "";
object o = oReflection.InstantiateClass(ref message);
if (o == null)
MessageBox.Show(message);
else
{
// go on with your processing
}

And here's the simplified class:

public class MyReflectionClass
{
#region Declarations
private string m_AssemblyName;
private string m_ClassName;
#endregion

#region Constructors
public MyReflectionClass()
{
}
/// If your Assemblies live in places other than the same path as your app,
/// you’ll need to modify this class to include code for obtaining the full path.
/// This full-path could be a local path, or a server URL path.
public MyReflectionClass(string assemblyName, string className)
{
this.AssemblyName = assemblyName;
this.ClassName = className;
}
#endregion

#region Methods

public Assembly LoadAssembly(ref string Message)
{
Assembly oAssembly = null;

try
{
// In my real class, I have configuration classes that handles this
string PathOrURL = MethodToObtainPathOrURL();
oAssembly = Assembly.LoadFrom(PathOrURL + this.m_AssemblyName + ".DLL");
}
catch (System.IO.FileNotFoundException)
{
Message = this.m_AssemblyName + " could not be found at the specified URL!" + (char)13 + (char)13 +
"Check that you have correctly entered the component URL and that your network or Internet " +
"connection is functioning correctly.";
return oAssembly;
}
catch (System.BadImageFormatException)
{
Message = this.m_AssemblyName + " is invalid or damaged!" + (char)13 + (char)13 +
"Contact your system administrator.";
return oAssembly;
}
catch (System.Exception ex)
{
Message = ex.Message;
return oAssembly;
}

return oAssembly;
}

public object InstantiateClass(ref string Message)
{
Assembly oAssembly = null;
return this.InstantiateClass(ref oAssembly, ref Message);
}
public object InstantiateClass(ref Assembly oAssembly, ref string Message)
{
object oClass = null;
if (oAssembly == null || oAssembly.FullName.Contains(this.m_AssemblyName) == false)
oAssembly = this.LoadAssembly(ref Message);

try
{
// Create an instance of the desired type from the assembly
if (oAssembly != null)
oClass = oAssembly.CreateInstance(this.m_ClassName);
}
catch (Exception ex)
{
Message = ex.Message;
return oClass;
}

return oClass;
}

#endregion

#region Properties
public string AssemblyName
{
get { return this.m_AssemblyName; }
set
{
this.m_AssemblyName = value.Trim();
if (this.m_AssemblyName.ToUpper().EndsWith(".DLL", true, null))
this.m_AssemblyName = this.m_AssemblyName.Remove(this.m_AssemblyName.Length - 4);
}
}
public string ClassName
{
get { return this.m_ClassName; }
set
{
this.m_ClassName = value.Trim();
if (this.m_ClassName.Contains(this.m_AssemblyName) == false)
this.m_ClassName = this.m_AssemblyName + "." + this.m_ClassName;
}
}
#endregion
}

No comments:

Post a Comment