An effective way to create a DSL is by building a thin layer that runs on top of a façade that interacts with the domain objects.
This is how those components looks in the sample app of this post.
In this case, the DSL only talk to the façade and the façade is in charge of talking with domains objects (or services or whatever component that goes underneath). This makes things really easy to implement and fit perfectly to work with Roslyn, because if we use the façade as the Roslyn script engine’s host object, the engine will let us access directly from our DSL syntax to any member of the façade's public API.
By looking at this unit test you will see how to wire up the components, execute the DSL script and modify the order state (the domain object) right from the DSL.
* If this were a real app, the order will continue with the processing pipeline.
So far so good, now how to go from our DSL syntax to façade calls?
* Notice that the facade exposes the domain object's state and/or behaviour..
If you take a look at the façade public API you will notice that almost every member matches with conditions and actions available on our DSL syntax (switching from Pascal Case to snake_case). As we mention earlier, any public member of the host object (in this case the façade) will be available right out of the box to our DSL, so with a little bit of source to source translation, this is pretty easy to achieve.
How to configure the façade as the engine’s host object
Configure the host object is pretty straight forward, it only takes a few lines of code.
And the rest of the work relies pretty much on source to source translation, which I will be covering in futures post.