How many times have you written a really nice reusable component for BizTalk and then after you have used it quite a lot a new requirement comes up and suddenly your nice reusable component suddenly has some completely scenario specific logic you need to implement. It happens a lot!
The challenge is how to minimize the impact on these things that are using the nice clean reusable component yet still create the logic required for the new requirement without creating a load of messy code. I usually see 2 ways teams have implemented this:
1. There is branching logic added to the reusable component so that if its the specific scenario then some extra stuff happens
2. A copy of the component is made and then the extra logic is added to the copy and usually no one really knows what to call the new thing
Neither of these are particularly nice!
Since following my last article we now know how we can use IoC containers in the BizTalk arena lets explore if we can use this to help us solve this problem.
In a previous blog post I wrote about a pipeline component I wrote which could do a streamed download of data from Dynamics CRM Online. This component was working really well in a few scenarios and was a very generic component. I simply passed it some fetch xml and told it where CRM was and what XML to wrap the download in. It would then just do its job and suddenly the output was there.
One day I got a new requirement which needed to manipulate the XML wrapper around the download data based on values that would be in the BizTalk message context. The problem was that this could be different for different scenarios. One instance might need to inject a date into it and another might want the message type or something else. The problem was how do I make my nice generic BizTalk pipeline component stay generic without having to write code like:
THEN manipulate the wrapper like this
ELSE IF manipulate the message some other way
I also didnt want to keep adding more instanced of the CRMDownloader so that we just end up with each instance having its own pipeline component so that it could have some extra logic.
In this case the scenario was perfect for a plug in or extension pattern and this could be implemented with Castle Windsor. What I did was:
- Specify a per instance pipeline component property which was added to the component which would specify an optional name for a plugin that would be ran
- In the loading of the container I would specify some named instances of services so I could have multiple objects which implement an interface but could request the one I want via a key (which comes from the new pipeline component property)
- I would call the extension I get from the pipeline component and let this seperate decoupled class execute the extension logic
The result of this was that my custom CRM download component was still nice and clean but I had a plug in pattern where I can handle any specific scenarios that one port may require but the others dont care about.
If you would like to see this in action check out the below video