Interface for Processes

I had to write one data import/export utility that moved data from one database to another. Once I was finished the first round of coding I found one thing that needed refactoring – the import/export process wasn’t generalized. It was part of importer/exporter utility main class (it was console application). After some refactoring I got some common things to use in other tasks like this.

My main idea was to extract interface for processes like this and then define some events. Let’s suppose we have process that reads invoices from one database and writes them after some data manipulation to other database. We receive list of invoices and then start processing them.

Process delegates

Every import/export process has start, processing part and finish. Processing part is step that is repeated for every data unit we are processing. All these three may be events that our processing class fires. Let’s define some delegates for these events.


delegate void ProcessStartDelegate(int count);
delegate void ProcessStepDelegate<T>(T obj, int index, int count);
delegate void ProcessFinishDelegate();

ProcessStartDelegate is fired when process starts. It is received input data and wants to start processing. Let’s say we have invoices as input data. As we have list of invoices we can say how many invoices we have. This is why ProcessStartDelegate has argument calles count.

ProcessStepDelegate is fired for every invoice we have. We want to use these delegates in different import/export processes, so we have to make ProcessStepDelegate generic because this way we can say type of object to it. Index is argument that shows the index of current invoice in input array. count is also there because some processes may change the input collection size during their work.

ProcessFinishDelegate is fired when process finishes. This delegate has no arguments because we already know how much elements we have.

Process interface

Now we have our delegates and we are ready to take the next step. Let’s define now interface for import/export processes. We want generic interface so we can use it also with other import/export classes. ProcessStepDelegate was generic and so we have to make our interface generic also. So here is our interface.


interface IProcess<T>
{
   
event ProcessStartDelegate
ProcessStart;
   
event ProcessStepDelegate
<T> ProcessStep;
   
event ProcessFinishDelegate
ProcessFinish;

   
void Process();
}

I added also method Process() this interface because we need something we can call to start the process. This interface is all we need here.

Example

Let’s see now simple example about how to use IProcess interface. As I said before we suppose we have class for invoices. We call this class Invoice.


public class InvoiceImporter : IProcess<Invoice>
{
   
public event ProcessStartDelegate
ProcessStart;
   
public event ProcessStepDelegate<Invoice
> ProcessStep;
   
public event ProcessFinishDelegate
ProcessFinish;

   
public
InvoiceImporter() { }

   
public void
Process()
    {

       
List<Invoice
> invoices = LoadInvoices();

       
if (this.ProcessStart != null
)
           
this
.ProcessStart(invoices.Count);

       
int
i = 0;

       
foreach (Invoice invoice in
invoices)
        {
           
if (this.ProcessStep != null
)
               
this
.ProcessStep(invoice, ++i, invoices.Count);

            ProcessInvoice(invoice);
        }

       
if (this.ProcessFinish != null
)
           
this
.ProcessFinish();
    }

   
private List<Invoice
> LoadInvoices()
    {
       
List<Invoice> invoices = new List<Invoice
>();

       
// Fill list here

       
return
invoices;
    }

   
private void ProcessInvoice(Invoice
invoice)
    {
       
// Do some processing here   
    }
}

This is simple skeleton of invoice importer. I follows completely IProcess interface. You can use this interface for different kinds of import/export classes to make sure they all follow the same pattern.


One thought on “Interface for Processes

Leave a Reply

Your email address will not be published. Required fields are marked *