In this article we will present a sample about how to use late binding in .NET using System.Reflection namespace and System.Type class.
What is Late Binding? – is a mechanism which allow to instantiate types and accessing members of objects created without knowing these types at compile time. Shortly, these types are not referred “classically”, through dot and new operators, but at runtime, acquiring information about structure type, instantiating objects and invoking its members. All of these without referring that type at all (anyway, we cannot do that, given that we did not include information about that type at compiling time.). All we need is to know structure of used type, more exactly, knowing what methods and properties we need to use.
This approach can be very useful in a lot of cases, due of these capabilities to manipulate objects at runtime, while they are unknown at compile time; this fact help us to provide a much more flexibility to our applications when interacting with others application and/or third-party software (such as COM).
Example – in the following example, we will manipulate objects from a .NET assembly using reflection mechanisms. In this assembly we have class Employee, which exposes some members and methods, and class EmployeeMethods, which exposes a collection of Employee objects and some methods which works on this collection. These 2 types (classes) will be used from main application (a website) without referring it at developing type, but operating on it at execution time. The referred assembly is stored on disk, and its location is given in web.config (you should copy it manually in this location).
Here is the code:
Code from assembly Objects.LateBinding.dll
using System;
using System.Collections.Generic;
namespace Objects.LateBinding
{
public class Employee
{
public string EmployeeName = "";
public int EmployeeAge = 0;
public string EmployeeFunction = "";
public Employee(string name, int age, string function)
{
EmployeeName = name;
EmployeeAge = age;
EmployeeFunction = function;
}
public string PresentEmployee()
{
return string.Format("Hi, I am {0}, {1} years old and I work as {2}", EmployeeName,EmployeeAge, EmployeeFunction);
}
}
public class EmployeeMethods
{
public List<Employee> Employees;
public void Init()
{
//in real scenarios, data will be loaded from various sources
Employees = new List<Employee>();
Employees.Add(new Employee("John", 26, "Programmer"));
Employees.Add(new Employee("Joe", 30, "Web developer"));
Employees.Add(new Employee("Jim", 40, "Software architect"));
}
public Employee GetEmployee(int i)
{
return Employees[i];
}
public int GetEmployeesCount()
{
return Employees.Count;
}
public void AddEmployee(string name, int age, string function)
{
Employees.Add(new Employee(name, age, function));
}
}
}
Code from Default.aspx.cs from main application:
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Reflection;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
public partial class _Default : System.Web.UI.Page
{
Assembly Asmb = null;
Type EmployeeMethods = null;
Type EmployeeType = null;
object EmpMethods = null;
protected void Page_Load(object sender, EventArgs e)
{
InitTypes();
if (!IsPostBack)
{
InitEmployees();
PresentEmployees();
}
}
private void InitTypes()
{
//get assembly with Employee classes
Asmb = Assembly.LoadFrom(System.Configuration.ConfigurationManager.AppSettings["TestAssembly"]);
//get EmployeeMethods type information
EmployeeMethods = Asmb.GetType("Objects.LateBinding.EmployeeMethods");
EmpMethods = Activator.CreateInstance(EmployeeMethods);
}
private void InitEmployees()
{
//invoke Init method on EmployeeMethods to init employee collection
MethodInfo mtdInfo = EmployeeMethods.GetMethod("Init");
mtdInfo.Invoke(EmpMethods, null);
}
private void PresentEmployees()
{
//get employees count from EmployeeMethods object created earlier
MethodInfo mtdInfoEmpCount = EmployeeMethods.GetMethod("GetEmployeesCount");
object employeesCount = mtdInfoEmpCount.Invoke(EmpMethods, null);
int emplCount = (int)employeesCount;
//get each employee object
for (int i = 0; i < emplCount; i++ )
{
object[] parEmpl = new object[] { i };
MethodInfo mtdInfoEmp = EmployeeMethods.GetMethod("GetEmployee");
object employee = mtdInfoEmp.Invoke(EmpMethods, parEmpl);//get employee
//invoke PresentEmployee method for current employee
EmployeeType = employee.GetType();
MethodInfo mtdInfoEmpPresent = EmployeeType.GetMethod("PresentEmployee");
object employeePresent = mtdInfoEmpPresent.Invoke(employee, null);
//display the 'response' of the method
Response.Write(employeePresent.ToString() + "<br/>");
}
}
private void AddEmployee(string Name, int Age, string Function)
{
//Add employee with values from interface
object[] parEmpl = new object[] { Name, Age, Function };
MethodInfo mtdInfoEmpAdd = EmployeeMethods.GetMethod("AddEmployee");
mtdInfoEmpAdd.Invoke(EmpMethods, parEmpl);
}
protected void btnAddEmployee_Click(object sender, EventArgs e)
{
InitEmployees();
AddEmployee(txtName.Text, int.Parse(txtAge.Text), txtFunction.Text);
PresentEmployees();
}
}
Code from Default.aspx:
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Late binding</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<table>
<tr>
<td colspan="2"><b>Add an employee:</b></td>
</tr>
<tr>
<td>Name:</td>
<td><asp:TextBox ID="txtName" runat="server"></asp:TextBox></td>
</tr>
<tr>
<td>Age:</td>
<td><asp:TextBox ID="txtAge" runat="server"></asp:TextBox></td>
</tr>
<tr>
<td>Function:</td>
<td><asp:TextBox ID="txtFunction" runat="server"></asp:TextBox></td>
</tr>
<tr>
<td colspan="2"><asp:Button ID="btnAddEmployee" runat="server" OnClick="btnAddEmployee_Click" Text="Add employee"/></td>
</tr>
</table>
</div>
</form>
</body>
</html>
In this example we list some employees, hardcoded, and add a new one through web interface, using only reflection mechanisms.
Note: Code is not optimized, and no validation was made, since is not point of interest in this article.
Prj.rar (7.70 kb)