Introduction
In this article, I will show how to load an assembly at runtime using Reflection and to invoke static methods from it.
Background
Reflection is Microsoft's extra-ordinary feature. Before we begin, we must know some very important concepts about assemblies. Assemblies are the building blocks of .NET Framework. An assembly is a collection of types and resources that are built to work together, and form a logical unit of functionality.
An assembly contains modules, modules contain types, and types contain members. Using Reflection, we can create an instance of a type, can invoke a type's methods, or access its fields and properties. For this tutorial, the above statement is enough. For a detailed information, click here.
Using the code
This tutorial consists of two projects:
- Utllity (the Class Library)
- LoadAssembly (application that will load Utility using Reflection)
The Utility Class Library consists of two methods:
Encrypt
(takes a string as input and returns the encrypted string as output)
- Decrypt (takes an encrypted string as input and returns the original string)
I will not discuss the utility code as it is not needed to. The utility code is as under:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Security.Cryptography;
namespace Utility
{
public static class Cryptography
{
public static string Decrypt(this string EncryptedText)
{
byte[] bytes = Encoding.UTF8.GetBytes("LcB!ZLtd");
byte[] rgbIV = Encoding.UTF8.GetBytes("!nforM@#");
byte[] buffer = Convert.FromBase64String(EncryptedText);
MemoryStream stream = new MemoryStream();
try
{
DES des = new DESCryptoServiceProvider();
CryptoStream stream2 = new CryptoStream(stream,
des.CreateDecryptor(bytes, rgbIV), CryptoStreamMode.Write);
stream2.Write(buffer, 0, buffer.Length);
stream2.FlushFinalBlock();
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
return Encoding.UTF8.GetString(stream.ToArray());
}
public static string Encrypt(this string PlainText)
{
byte[] bytes = Encoding.UTF8.GetBytes("LcB!ZLtd");
byte[] rgbIV = Encoding.UTF8.GetBytes("!nforM@#");
byte[] buffer = Encoding.UTF8.GetBytes(PlainText);
MemoryStream stream = new MemoryStream();
try
{
DES des = new DESCryptoServiceProvider();
CryptoStream stream2 = new CryptoStream(stream,
des.CreateEncryptor(bytes, rgbIV), CryptoStreamMode.Write);
stream2.Write(buffer, 0, buffer.Length);
stream2.FlushFinalBlock();
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
return Convert.ToBase64String(stream.ToArray());
}
}
}
LoadAssembly
The LoadAssembly project will load the assembly using Reflection and will invoke the methods. The code with the explanation is as under.
The variables that will be used in the application are:
Type[] TypesInAssembly = null;
string AssemblyName = string.Empty;
string AssemblyPath = string.Empty;
string ExecutingAssemblyPath = string.Empty;
object Result, DecryptedResult = null;
Form load
On the Form load, the application will load Utility.dll, which then will be used by the button events to invoke the methods. The Form load event code is shown here:
ExecutingAssemblyPath = Application.StartupPath;
ExecutingAssemblyPath =
System.IO.Path.GetDirectoryName(ExecutingAssemblyPath);
AssemblyPath = ExecutingAssemblyPath + "\\" +
ConfigurationManager.AppSettings["Location"].ToString() +
ConfigurationManager.AppSettings["Assembly"].ToString();
System.Reflection.Assembly MyAssembly =
System.Reflection.Assembly.LoadFrom(AssemblyPath);
TypesInAssembly = MyAssembly.GetTypes();
AssemblyName = TypesInAssembly[0].Namespace + "." + TypesInAssembly[0].Name;
System.Reflection.MethodInfo[] MethodsCollection = TypesInAssembly[0].GetMethods();
Invoking methods
Before you do an invoke, you must know about invoking a static method. For a static method to be invoked, there is a parameter named 'target'. If you are invoking a static method, then leave this parameter as blank, this will be ignored by the framework. If your method is not static, then you have to provide the instance of the class and that instance will be creating the CreateInstance
method. In our case, we are calling a static method.
Here are the button events that will be invoking the Utility.dll member methods:
private void bttnEncrypt_Click(object sender, EventArgs e)
{
try
{
Result = TypesInAssembly[0].InvokeMember("Encrypt",
System.Reflection.BindingFlags.InvokeMethod, System.Type.DefaultBinder,
"", new object[] { txtMessage.Text });
txtEcnryptedMessage.Text = Result.ToString();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void bttnDecrypt_Click(object sender, EventArgs e)
{
try
{
DecryptedResult = TypesInAssembly[0].InvokeMember("Decrypt",
System.Reflection.BindingFlags.InvokeMethod, System.Type.DefaultBinder,
"", new object[] { txtEcnryptedMessage.Text });
MessageBox.Show(DecryptedResult.ToString());
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}