zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    【嵌入式开发】写入开发板Linux系统-模型S3C6410
    大约cocos2d-X 3.x使用引擎版本自带的物理引擎Physics
    它们的定义PropertyPlaceHolder无法完成更换任务
    [Cocos2d-x]在Cocos2d-x 3.x如何通过版本号WebSocket连接server数据的传输
    Java 内存架构
    类似的微博推断客户关系sql声明
    Kienct与Arduino学习笔记(2) 深度图像与现实世界的深度图的坐标
    etl工具,kettle实现了周期
    Android中自定义checkbox样式
    ndroid网络(4):HttpClient必经之路----使用线程安全的单例模式HttpClient,及HttpClient和Application的融合
  • 原文地址:https://www.cnblogs.com/2018/p/2623623.html
Copyright © 2011-2022 走看看