Chain of Responsibility Using Castle Windsor and a First Experience With StructureMap - Part 1
November 16, 2008A couple of months ago, I applied the Chain of Responsibility pattern for the very first time. I've never encountered a scenario before where applying this pattern would be a valid option. But now, after some refactoring, I somehow naturally ended up applying this rarely used design pattern. Lets dive into some code, shall we?
public interface IProcessor
{
IProcessor Successor
{ get; set; }
void Process(Request request);
}
public abstract class BaseProcessor : IProcessor
{
public IProcessor Successor { get; set; }
public void Process(Request request)
{
// Some base class behaviour
FurtherProcess(request);
if(null != Successor)
{
Successor.Process(request);
}
}
protected abstract void FurtherProcess(Request request);
}
This is the base class for all processor classes (bad naming, huh?) . If there is a follow-up processor available, then its Process method is called. The processor classes can now focus on their main responsibility:
public class Processor1 : BaseProcessor
{
protected override void FurtherProcess(Request request)
{
// Do something usefull
}
}
I'm using Castle Windsor to chain together the different processors in the particular order that I want. This involves setter injection for the Successor property. Although I'm not a huge fan of setter injection, in this case it seems like a viable option. The following example uses the fluent interface of Castle Windsor for configuring the container:
_container.Register(
Component.For<ProcessorConsumer1>()
.Named("ProcessorConsumer1")
.Parameters(Parameter.ForKey("processor")
.Eq("${Processor1}")),
Component.For<IProcessor>()
.Named("Processor1")
.ImplementedBy<Processor1>()
.Parameters(Parameter.ForKey("Successor")
.Eq("${Processor2}")),
Component.For<IProcessor>()
.Named("Processor2")
.ImplementedBy<Processor2>());
Nothing much to it. The ProcessConsumer class simply gets the first processor injected through its constructor. The above configuration results in the following chain:
ProcessConsumer1 -> Processor1 -> Processor2
Everything is fine and dandy so far. Now suppose that I want to add another ProcessConsumer that requires a slightly enhanced chain of processors like so:
ProcessConsumer1 -> Processor1 -> Processor2
ProcessConsumer2 -> Processor3 -> Processor1 -> Processor2
This is how the configuration of Castle Windsor now looks like:
_container.Register(
Component.For<ProcessorConsumer1>()
.Named("ProcessorConsumer1")
.Parameters(Parameter.ForKey("processor")
.Eq("${Processor1}")),
Component.For<ProcessorConsumer2>()
.Named("ProcessorConsumer2")
.Parameters(Parameter.ForKey("processor")
.Eq("${Processor3}")),
Component.For<IProcessor>()
.Named("Processor1")
.ImplementedBy<Processor1>()
.Parameters(Parameter.ForKey("Successor")
.Eq("${Processor2}")),
Component.For<IProcessor>()
.Named("Processor2")
.ImplementedBy<Processor2>(),
Component.For<IProcessor>()
.Named("Processor3")
.ImplementedBy<Processor3>()
.Parameters(Parameter.ForKey("Successor")
.Eq("${Processor1}")));
With this particular configuration, Castle Windsor now throws an exception with the following description:
A cycle was detected when trying to resolve a dependency.
After some investigation it seems that Castle Windsor wants to set the Successor property of Processor2 with the instance of Processor1, which is not what I had in mind. The Successor property of Processor2 should remain empty. I believe this has something to do with the approach that Castle Windsor is taking to never inject a null reference, although I'm not completely sure.
Anyway, I got around this issue by splitting up the IProcessor interface and the BaseProcessor class as outlined in my next post.
If you and your team want to learn more about how to write maintainable unit tests and get the most out of TDD practices, make sure to have look at our trainings and workshops or check out the books section. Feel free to reach out at info. @ principal-it .be
Jan Van Ryswyck
Thank you for visiting my blog. I’m a professional software developer since Y2K. A blogger since Y2K+5. Provider of training and coaching in XP practices. Curator of the Awesome Talks list. Past organizer of the European Virtual ALT.NET meetings. Thinking and learning about all kinds of technologies since forever.
Comments
Writing Maintainable
Unit Tests
Watch The Videos
Latest articles
-
Contract Tests - Parameterised Test Cases
June 28, 2023
-
Contract Tests - Abstract Test Cases
April 12, 2023
-
Contract Tests
February 1, 2023
-
The Testing Quadrant
June 15, 2022
-
Tales Of TDD: The Big Refactoring
February 2, 2022
Tags
- .NET
- ALT.NET
- ASP.NET
- Agile
- Announcement
- Architecture
- Behavior-Driven Development
- C++
- CQRS
- Clojure
- CoffeeScript
- Community
- Concurrent Programming
- Conferences
- Continuous Integration
- Core Skills
- CouchDB
- Database
- Design Patterns
- Domain-Driven Design
- Event Sourcing
- F#
- Fluent Interfaces
- Functional Programming
- Hacking
- Humor
- Java
- JavaScript
- Linux
- Microsoft
- NHibernate
- NoSQL
- Node.js
- Object-Relational Mapping
- Open Source
- Reading
- Ruby
- Software Design
- SourceControl
- Test-Driven Development
- Testing
- Tools
- Visual Studio
- Web
- Windows
Disclaimer
The opinions expressed on this blog are my own personal opinions. These do NOT represent anyone else’s view on the world in any way whatsoever.
About
Thank you for visiting my website. I’m a professional software developer since Y2K. A blogger since Y2K+5. Author of Writing Maintainable Unit Tests. Provider of training and coaching in XP practices. Curator of the Awesome Talks list. Thinking and learning about all kinds of technologies since forever.
Latest articles
Contract Tests - Parameterised Test Cases
Contract Tests - Abstract Test Cases
Contract Tests
The Testing Quadrant
Contact information
(+32) 496 38 00 82
info @ principal-it .be