dsl boo3个例子 9

ƒ The Message-Routing DSL is an example of an imperative DSL. It’s executed to

perform some goals.

ƒ The Authorization DSL is a more declarative example (but still mostly impera-

tive). It’s executed to produce a value, which is later used.

ƒ The Quote-Generation DSL is a mostly declarative example. It produces an

object graph that’s later taken up by the processing engine.

Message-Routing DSL

The main reason that we want to use a DSL here is to keep the system flexible and

make it easy to add new messages and transformations. This DSL will be used by tech-

nical people, most probably the developers on the project. This, in turn, means that

we can use a technical DSL here. Each script using this DSL will probably have the fol-

lowing responsibilities:

ƒDeciding whether the script can handle the message

ƒTransforming the message to the internal message representation

ƒDeciding where to dispatch the message

clip_image001

RouteNewOrder.boo DSL定义

# decide if this message match this DSL script

return if msg.type != "NewOrder" and msg.version == "1.0"

# decide which handle is going to handle it

HandleWithNewOrderHandler:

# define a new list

lines = []

# add order lines to the list

for line in msg.order_lines:

lines.Add(OrderLine( line.product, line.qty ) )

# create internal message representation

returnNewOrderMessage(

msg.customer_id,

msg.type,

lines.ToArray(OrderLine) )

clip_image003

IQuackFu it allows us to handle unknown method calls at runtime in asmart fashion.

RoutingBaseThe Message-Routing DSL script will be compiled into a class thatinherits from RoutingBase, and all the code in the script
 will go into the Route()method, while the  msg field will contain the current message during execution
RoutingDslEnginecompile this DSL. We do it using a DSL engine
RouterThe Routerclass hook it up to the Routerclass

使用:

// translate from the post body to a json object
byte[] bytes = context.Request.BinaryRead(context.Request.TotalBytes);
string json = Encoding.UTF8.GetString(bytes);
JsonSerializer jsonSerializer = new JsonSerializer();
JsonReader reader = new JsonReader(new StringReader(json)); JavaScriptObject javaScriptObject = (JavaScriptObject)jsonSerializer.Deserialize(reader);

// send the json object to be routed
string scriptsPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "bin");
string returnMessage = Router.Route(scriptsPath,
new JsonMessageAdapter(javaScriptObject));
context.Response.Write(returnMessage);

context.Response.Write(returnMessage);

JsonMessageAdapter class is responsible for translating the JavaScriptObject into an IQuackFu, which is what we expect in the MessageRouting DSL

using Boo.Lang;
using Newtonsoft.Json;
public class JsonMessageAdapter : IQuackFu
{
private readonly JavaScriptObject js;
public JsonMessageAdapter(JavaScriptObject js)
    {
this.js = js;
    }
public object QuackGet(string name, object[] parameters)
    {
object value = js[name];
JavaScriptArray array = value as JavaScriptArray;
if(array!=null)
        {
return array.ConvertAll(delegate(object obj)
            {
return new JsonMessageAdapter((JavaScriptObject) obj);
            });
        }
return value;
    }

 
 

Authorization DSL

clip_image005

ƒThe CheckAuthorization() method and the Operation property are both

abstract, so derived classes (and our DSL) have to implement them.

ƒThe Allow() and Deny() methods are the only ways for the derived class to

affect the state of the rule. Both methods accept a reason string, which means

that we’re automatically documenting the reason for the decision.

operation "/account/login"

if Principal.IsInRole("Administrators"):
        Allow("Administrators can always log in")
        return

if date.Now.Hour < 9 or date.Now.Hour > 17:
        Deny("Cannot log in outside of business hours, 09:00 - 17:00")

e make use of the Boo date keyword

to reference System.DateTime, which we haven’t seen before, but that isn’t very

interesting.

There is one interesting thing here: the first line isn’t something that we’ve seen so

far. We know that we need to provide an implementation of the Operation property,

but how can we do it?

It’s done using a macro, which takes the first argument of the macro, generates a

property, and returns that argument from the property.

使用

 WindowsPrincipal principal = new WindowsPrincipal(WindowsIdentity.GetCurrent());
bool? allowed = Authorization.IsAllowed(principal, "/account/login");
Console.WriteLine("Allowed login: {0}", allowed);
Console.WriteLine(Authorization.WhyAllowed(principal, "/account/login"));

The Quote-Generation DSL

clip_image007

The first is that we use astrange naming convention for some of the methods (requires, same_machine_as,specification, and users_per_machine do not follow the standard .NET namingconvention). This is the easiest way to get keywords in the DSL.

Note that thespecification() method accepts a delegate as the last parameter, so we’re using

anonymous blocks again, like we did in the Message-Routing DSL Handle method.

The second thing to note is all the @ signs scattered through the DSL (listing 4.16).

Those are called symbols, and they translate to string literals without the annoying

The last thing that’s worth noting about the QuoteGeneratorRule class is that itaccepts a RequirementsInformation class. This allows it to understand what context itruns in, which will be important later on.

The QuoteGeneratorRule class is responsible for building the object model thatwill later be processed by the quote-generation engine.

specification @vacations:
        requires @scheduling_work
        requires @external_connections
       
specification @salary:
        users_per_machine 150
       
specification @taxes:
        users_per_machine 50

specification @pension:
        same_machine_as @health_insurance
posted @ 2012-11-05 11:51  2012  阅读(481)  评论(0编辑  收藏  举报