Introduction
Application Framework to plug components - Part I has already explained how to build pluggable components to a framework and invoke methods in such a component. In a typical component, the component itself has to initiate and invoke methods in its framework. This article describes how to use interfaces in calling back functions in the framework.
How it works....
As I described in my previous article, a proxy DLL contains interfaces which build the bridge between the framework and component. To deal with events, the proxy DLL has to declare an interface which describes all possible events that the framework should get notified of. This interface which describes the callback functions in a framework is implemented and instantiated in the application framework. And a reference to this object instance is passed to the relevant component using .NET reflection. Having a reference to an object instance in the framework, the component could invoke any method in that object instance which resides in the application framework.
Using the code
The demo project implements simple mathematical operations on two integers with interfaces. An event gets fired in an attempt to divide a number by zero, and at the same time, there is a button on a form which could simulate an event on the component.
MathProxy.dll consists of two interfaces, namely IMath
and IMathEvent
. As the name implies, IMathEvent
describes the function prototypes of events that get invoked in the application framework. Here, the CalcErrorEvent
is the only function in the interface and it just passes a string to the framework.
public interface IMath
{
int CalcValues(int iValue1, int iValue2);
}
public interface IMathEvent
{
void CalcErrorEvent(string s);
}
The IMathEvent
interface is implemented in the application framework as the MathEvent
class. MathEvent
has a member from the parent class which is the central location for application the framework. This is only to access the framework from the event interface. Here goes the class implementation:
public class MathEvents : IMathEvent
{
public frmIntfDemo m_form;
void IMathEvent.CalcErrorEvent(string s)
{
m_form.txtEventMsg.Text = s;
}
}
frmIntfDemo
is the application framework at this point and it has a member of type MathEvent
. The MathEvent
class gets instantiated at the constructor of frmIntfDemo
and a reference to the startup module is saved in the MathEvent
class.
m_mathEvent = new MathEvents();
m_mathEvent.m_form = this;
Now, let's have a look at how the component gets created. Here I have used CreateEx
instead of Create
just to differentiate this implementation from the previous article's implementation. The CreateIntf
has three static members namely m_MathEvent
, m_div
and m_ComponentUI
. These members hold references to the MathEvent
instance created in the application framework, the Div
class instance which implements the IMath
interface and a form instance which is used to simulate events by the component respectively. (Here the frmComponentUI
's sole purpose is to initiate an event with user interaction.)
public class CreateIntf
{
static IMathEvent m_MathEvent;
static Div m_div;
static frmComponentUI m_ComponentUI;
static public IMath CreateEx(IMathEvent mathEvent)
{
m_MathEvent = mathEvent;
m_div = new Div();
m_div.m_Events = m_MathEvent;
m_ComponentUI = new frmComponentUI();
m_ComponentUI.m_mathEvent = m_MathEvent;
m_ComponentUI.Show();
return m_div;
}
}
The Div
class implements the IMath
interface and has a reference to the IMathEvent
implementation (MathEvent
) in the application framework as well. If we take a closer look on the CalcValues
implementation, you can see that, when the denominator is zero, the function calls CalcErrorEvent
of the IMathEvent
interface. This notifies the application framework for a divide by zero error.
public class Div : IMath
{
public IMathEvent m_Events;
int IMath.CalcValues(int iValue1,int iValue2)
{
int iRes=0;
if ( iValue2 == 0 )
m_Events.CalcErrorEvent( "Device by Zero Error" );
else
iRes = iValue1 / iValue2;
return iRes;
}
}
In the frmComponentUI
, btnSimulate_Click
has code to simulate a CalcErrorEvent
.
private void btnSimulate_Click(object sender, System.EventArgs e)
{
m_mathEvent.CalcErrorEvent( "Error event simulate by Component UI" );
}
Conclusion
This article along with Application Framework to plug components - Part I describes how to build a simple application framework which could plug components at runtime using .NET reflection and interfaces.