Introducing NDecision.Aspects

If you've not gotten up to speed with the core functionality provided via NDecision it might be good to take a look at the release announcement, which you can find here.

If you're into Aspect-Oriented Programming or you like things to be a little more dynamic and automatic, a second option exists that you might find interesting. The NDecision.Aspects package makes use of the amazing AOP product PostSharp, by SharpCrafters, to enable logic execution automatically at run-time. Rather than write your logical specifications inline, you implement the IHasSpec<T> interface. This interface's single method, GetSpec(), allows you the freedom of wiring up your logic in one place (or in many places, if you prefer to have your specifications split into individual classes based on your own need or preferences). 

Refactoring the Example for NDecision.Aspects

I'll build on the previous example and refactor the code to use the NDecision.Aspects package and to provide some insight into the difference. First of all, the logic from the original code has been moved into an implementation of the IHasSpec<BugsBunny> interface. 

Implementing the rules for an object in an IHasSpec implementation

Once your IHasSpec<T> implementation has been written, the majority of the work is complete. To use the specifications outlined in the IHasSpec<T> implementation, the ApplySpecsBeforeExecution (or ApplySpecsAfterExecution) attribute class can be used to decorate the methods whenever the specifications need to be applied. The screen shot below demonstrates how, using the ApplySpecsBeforeExecution attribute, the rules will automatically be applied prior to the method's logic being executed. 

Method with a parameter decorated for automatic specification application

If a second parameter for which there existed IHasSpec<T> implementations were placed on this method, specifications for that parameter would be picked up too. In this way, AOP takes over - for any parameter added to this method for which there exists an IHasSpec<T> implementation, the specifications will be dynamically found and executed on the parameter instance at run-time.

Your rules, in a sense, are automatically applied whenever you want them to be applied. 

NDecision with AOP, Option Two - Self-Awareness

Now, there may exist a circumstance where your object instances - in this case our favorite childhood cartoon character - should be allowed to do their own work based on the specifications and how they should be applied. In these cases it would be more optimal to have the capability of applying the ApplySpecsBeforeExecution or ApplySpecsAfterExecution attributes to the target class itself (or specifically, to methods of the target class). The code from above has been refactored with this idea in mind. Specifically, we've given Bugs his own method, also decorated with the ApplySpecsBeforeExecution attribute. 

Self-driven functionality

Likewise, the program code will need to be changed so that it allows Bugs his autonomy.

Allowing the target class to drive itself

Both methods result with the following obvious output - a console window showing the directions Bugs takes on his journey, in the order they were taken. 

Output of the demonstration code

Just like the NDecision core project, NDecision.Aspects is available for free via NuGet. Don't worry about the dependencies or having to install both packages; simply installing NDecision.Aspects will bring down everything you need, including the PostSharp assembly, as SharpCrafters so generously offer it up as a NuGet package too. 

NDecision.Aspects NuGet install

Happy coding! I hope you give NDecision a spin. If you do take the time to play with it, please let me know how it works out for you via the comments form. Or, you can find me on Twitter at @bradygaster.