The purpose of this tutorial is to demonstrate how to create a very simple
snappable application in C#.
Preview
The above screenshot shows a snappable application with one plugin loaded.
The text in the list box originated from the plugin itself.
Introduction
A snappable application is simply a program that can be extended using
assemblies (DLL's) that the application has no knowledge of at runtime.
A snappable application can load external assemblies and then call their
methods dynamically at runtime. This functionality has lots of uses, but is
mainly to allow developers to create third party add-ins.
This tutorial is trivial, but demonstrates all of what is needed to
implement snap-ins.
Reflection
Before we can get started, we need to understand a little bit about what
Reflection (System.Reflection) is, as this is fundamental to our project.
Reflection allows us to learn about an assembly at runtime with no prior
knowledge. Reflection, in its simplest form, can be used to determine the
properties of an assembly (such as its interfaces, methods, properties,
events etc) and bind to the (late bind) and use them at runtime. At
runtime, we can dynamically load an external assembly, and make calls to its
methods.
Creating a snappable application
To make our application snappable, we will need the following;
- Our main application (called MyApplication in this tutorial)
- An interface library (called MyApplicationInterface)
- A snap-in (called MySnapIn)
The main application will host the snap-in, the interface library will
expose interfaces that can be used by third party developers and the snap-in
will implement the interface library.
Interface Library (MyApplicationInterface)
The purpose of this library is to expose interfaces that can be implemented
by third party developers. Our main application will also have a reference
to this interface. When we dynamically load our snap-in at runtime, we will
look for this interface in the assembly and then invoke its method.
Start by creating a project called "MyApplicationInterface" and add a class
called "IMyApplication.cs". Add the following code;
namespace MyApplicationInterface
{
public interface IMyApplication
{
string Name
{ get;
}
}
}
n this scenario, the interface has one property which is used to
retrieve the name of the snap-in.
Snap-in (MySnapIn)
Next, create a class library called MySnapIn, create an empty class, and
implement the interface we just created. (Make sure you add a reference to
MyApplicationInterface.dll)
using MyApplicationInterface;
namespace MySnapIn
{
public class MySnapIn : IMyApplication
{
#region Implementation
of IMyApplication
public string Name
{
get { return "My
Snap In"; }
}
#endregion
}
}
Main Application (MyApplication)
All that is left to do is load our snap-in and display its name to the
user.
Create a new Windows Forms application called MyApplication, add a reference
to MyApplicationInterface.dll and add the following code;
private void LoadSnapIn(string snapInPath)
{
if (string.IsNullOrEmpty(snapInPath)) return;
if (!File.Exists(snapInPath)) return;
try
{
//Load the assembly
Assembly thirdPartySnapIn
= Assembly.LoadFrom(snapInPath);
//Search for class which implemented
IMyApplication
Type[] snapInTypes =
thirdPartySnapIn.GetTypes();
foreach(Type type in snapInTypes)
{
if (type.GetInterface("IMyApplication")
!= null)
{
//We have found a class that
implements our interface
//Late bind to it.
IMyApplication snapInInterface
= thirdPartySnapIn.CreateInstance(type.FullName) as IMyApplication;
if (snapInInterface
!= null)
{
//Retrive the 'Name' of the
snap-in, display it to the user
LoadedSnapinsListBox.Items.Add(snapInInterface.Name);
}
}
}
}
catch(Exception ex)
{
HandleException(ex);
}
}
The above code loads the assembly, searches for a class which
implements our interface IMyApplication, and if it finds one, returns the
value of the Name property (which is then displayed to the user.
Conclusion
We can use reflection to dynamically load assemblies at runtime and use late
binding to dynamically invoke methods and properties of which we had no
prior knowledge. This example, although trivial, shows how simple it is to
create a flexible application which can be extended by third party
developers.