Decorating method calls
A common feature of aspect-oriented programming is the ability to respond to the occurrence of a certain event by performing an action. A typical application of this is, for instance, to respond to the deletion of a user (something which is handled by a user-management module) by also removing that user’s access rights (this is done by the rights-management module, of which the user-management module is unaware) and that user’s personal documents (done by yet another independent module).
This particular pattern also exists in graphical user interfaces, when certain user input operations trigger events that may be forwarded to any number of listeners.
In this proposed implementation, every decorated method comes in four pieces : a call-binder object which is used to store listeners and forward function calls, a front-office function which is publically available for calling (and which is the one being decorated), a function for accessing the binding object, and a function for actually implementing the function being decorated. For instance:
class example = object val act_bind = new callbind method act = act_bind # call () (self # act_impl) method act_bind = act_bind method private act_impl () = print_endline "Call!" end let _ = let ex = new example in ignore (ex # act_bind # before (fun () -> print_endline "Before!")) ; ignore (ex # act_bind # after (fun () -> print_endline "After!")) ; ex # act
Implementation
The implementation consists in storing a list of functions to be called for both events (before the call and after the call), with the appropriate removal semantics (adding an element returns a unique identifier which can be used to remove the function).
type binding = int let add e = function | [] -> (0:binding), [0,e] | ((n,_)::_) as l -> (n+1), (n+1,e)::l let rec rm (i:binding) = function | [] -> [] | (j,f)::t -> if i = j then t else (j,f)::(rm i t) class ['a,'b] callbind = object val mutable before = [] val mutable after = [] method call (arg:'a) (f:'b) = List.iter (fun (_,x) -> x arg) before ; let result = f () in List.iter (fun (_,x) -> x arg) after ; result method before f = let (i,l) = add f before in before <- l ; i method after f = let (i,l) = add f after in after <- l ; i method rm_before i = before <- rm i before method rm_after i = after <- rm i after end
Hi. I'm Victor Nicollet,
0 Responses to “Before-After Binding”