In enterprise applications, we may use a common form in many places, but the result from that form needs to be used in different business logic. The form cannot return a result. So the question would be how we can reuse a common form in different scenarios. For example, a custom confirmation dialog form or in a POS application, there will be a common tender form for sales receipt and invoice, but the business logic involved using the tender data will be different in sales receipt and invoice. As the form can't return anything, it has to call two different types of logic which makes this form tightly coupled and not reusable.
Dependency injection principle is design pattern that helps in this situation. For more details about dependency injection, refer to Dependency Injection for Loose Coupling
Here we inject a delegate to make the form decoupled and reusable. For the demo, I have a form (form1
) with two buttons (button1
and button2
) and two labels (label1
and label2
). I have a second form with two buttons (button1
and button2
) and a static
label whichever text is in it. When I click each button, the form2
will be opened. Clicking the form2
buttons it calls function which it knows only at RUNTIME. So the form doesn't know anything it is going to do in design time, it only shares its data but not knowing the logic to execute. For this decopupling, we can use delegate. In the form, one declares a delegate.
public delegate void invokeConfirmationCallback();
Once declared, the delegate instantiates the delegate with the desirable function it has to point.
invokeConfirmationCallback confirmCallback = new invokeConfirmationCallback(handleButton1Confirmation);
In the form2
, declare a variable of the wrapper class Delegate
.
private Delegate confirmDelegate;
Assign the instantiated delegate in the form1
to form2
's delegate variable.
confirmForm = new Form2();
confirmForm.setConfirmHandler(confirmCallback);
Invoke the delegate in the form2
events.
confirmDelegate.DynamicInvoke();
In this way, we can tell form2
at runtime which business logic it has to execute and reuse it anywhere in the application.
The complete source dump of form1
is as follows:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace EventDelegates_Demo
{
public partial class Form1 : Form
{
public delegate void invokeConfirmationCallback();
private Form2 confirmForm;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void button1_Click(object sender, EventArgs e)
{
invokeConfirmationCallback confirmCallback = new invokeConfirmationCallback(handleButton1Confirmation);
invokeConfirmationCallback rejectCallback = new invokeConfirmationCallback(handleButton1Reject);
confirmForm = new Form2();
confirmForm.setConfirmHandler(confirmCallback);
confirmForm.setRejectHandler(rejectCallback);
confirmForm.Show();
}
private void handleButton1Confirmation()
{
confirmForm.Close();
label2.Text = "Action 1 Request Confirmed";
}
private void handleButton1Reject()
{
confirmForm.Close();
label2.Text = "Action 1 Request Rejected";
}
private void button2_Click(object sender, EventArgs e)
{
invokeConfirmationCallback confirmCallback = new invokeConfirmationCallback(handleButton2Confirmation);
invokeConfirmationCallback rejectCallback = new invokeConfirmationCallback(handleButton2Reject);
confirmForm = new Form2();
confirmForm.setConfirmHandler(confirmCallback);
confirmForm.setRejectHandler(rejectCallback);
confirmForm.Show();
}
private void handleButton2Confirmation()
{
confirmForm.Close();
label2.Text = "Action 2 Request Confirmed";
}
private void handleButton2Reject()
{
confirmForm.Close();
label2.Text = "Action 2 Request Rejected";
}
}
}
The complete source code of Form2
is as shown below:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace EventDelegates_Demo
{
public partial class Form2 : Form
{
private Delegate confirmDelegate;
private Delegate rejectDelegate;
public Form2()
{
InitializeComponent();
}
private void Form2_Load(object sender, EventArgs e)
{
}
public void setConfirmHandler(Delegate confirmDelegate)
{
this.confirmDelegate = confirmDelegate;
}
public void setRejectHandler(Delegate rejectDelegate)
{
this.rejectDelegate = rejectDelegate;
}
private void button1_Click(object sender, EventArgs e)
{
confirmDelegate.DynamicInvoke();
}
private void button2_Click(object sender, EventArgs e)
{
rejectDelegate.DynamicInvoke();
}
}
}