Fun with Pipelining, Chaining & Linq – P1
This is a long series of entries around rules processing & chaining. Bear with me :-)
Pipelines are among my favorite method to express sequence of logic components to execute in response to business events like “save new customer” button or “Process New Customer” service method. Developing pipelines was always about creating a pipeline interface (preferably an abstract class) that expresses the following:
- Component name
- Execute method that has a known parameter.
Then developing a pipeline that stages these components in a sequence with a mechanism to start executing so your pipeline will probably have method around:
- Add Pipeline component
- Remove Pipeline component
- Execute (this is where the real fun, to look across all components and execute them one by one)
This was fun to develop, and always interesting to start optimizing and adding feature like persisting the structure of the pipeline (to DB or file), or adding shared services like DB connectivity, service URL etc.
Check out BTS pipeline interfaces they are a well implemented example of the above.
With .NET anonyms methods, extension methods this has become really easy to accomplish like this sample pseudo code:
var ActionsArray = {Action1, Action2, Action3}
ActionArray.Execute(CustomerInstance)
Now enough talk and let us jump to code (all code is attached to this post)
I have a customer type that looks like this
class Customer
{
public string Name { get; set; }
public Address Address {get;set;}
public readonly string Id;
}
class Address
{
public string Street{ get; set; }
public string City { get; set; }
public string ZipCode { get; set; }
}
A sample initialized customer will probably looks like this
Customer newCustomer = new Customer
{
Name = "Khaled Hnidk",
Address = new Address
{
Street = "No Where Land",
City = "Cairo, Egypt",
ZipCode = "00000"
}
};
I have a series of methods I want to chain the execution like the following
public static void SaveCustomer (Customer c)
{
Console.WriteLine("SAVE CUSTOMER");
}
public static void ValidateCustomer(Customer C)
{
//throw exception here if customer is not valid
Console.WriteLine("Validate Customer");
}
public static void RefreshCache()
{
Console.WriteLine("REFRESH Cache");
}
Here is how I am going to build my pipeline
Action<Customer>[] pipeline =
{
c => ValidateCustomer(c),
c => SaveCustomer(c),
c => RefreshCache()
};
Discussion: what I am doing is building an array of Action delegate available in System namespace which is nothing other than a function pointer. And I am using anonymous methods to execute my validation methods in sequence, this array can be built using configuration
Table in your DB or configuration file. The interesting thing about this approach is, it isolates the processing sequence from your code
Then I am executing the pipeline like this
pipeline.ExecuteForEach(act => act(newCustomer));
How did this happen, I am using a mechanism inside .NET that was built organically to support Linq, Arrays by definition implements IEnumerable interface, which I have extended (using extension methods) as the following:
public static void ExecuteForEach<t>(this IEnumerable<t> IEnum, Action<t> toExecute)
{
foreach (var item in IEnum)
toExecute(item);
}
Next we discuss how to load these actions from configuration files.
Find me on Twitter: https://twitter.com/khnidk