Method Wrappers can add hidden behavior to a method without recompiling it. They can be used to change a method's behavior. Commonly, they are used to add behavior before and after the default method executes. For example, we can create a coverage tool by using a method wrapper that increments a counter when it is called. If you would like more detailed information about method wrappers, you can read the ECOOP'98 paper Wrappers to the Rescue.
WARNING: Incorrectly using the wrappers can crash your image, so you should save your image before using them. Most problems occur as a result of installing them on methods that are called either in thebeforeMethod or afterMethod which results in infinite recursion.
User Instructions:
To install the method wrappers, simply parcel-in the MethodWrapperBase.pcl file from MethodWrappers.zip into a VisualWorks image. The other files can be parceled-in in any order or not at all. Both the Synchronization Wrappers and the Method Wrapper Example parcels have examples of specialized method wrappers. The Synchronization Wrappers can be used to synchronize messages on an object. Once loaded you can send the #synchronize messages to any object to synchronize all messages to that object. The other two parcels, Coverage Tool and Interaction Diagram, have their own pages of documentation.
To use a method wrapper, send the class an on:inClass: message to the class of the method wrapper you want to create. The first argument is the selector for the method, and the second is the class that defines the method. This returns a new method wrapper which can then be installed the by sending the install message and uninstalled by sending uninstall message.
To create a new type of method wrapper, you must create a subclass of MethodWrapper and redefine the beforeMethod and/or afterMethod to add your specific behavior for the wrapper. If you only need to redefine the beforeMethod, you can redefine the valueFrom:arguments: method instead (see the CountMethodWrapper). This is somewhat faster since it doesn't need to create two blocks and send the valueNowOrOnUnwindDo: message.
Bugs/Limitations:
- If you recompile a method that has a method wrapper, the wrapper will not be installed on the new method. This behavior can be changed by modifying a couple of methods in class Behavior, but this seemed like the best idea. Note: when you add or remove an instance variable from a class, the class must recompile all methods associated with the class, so it will lose all wrappers.
- You cannot view the decompiled source code of a wrapper method. Since the wrapper method refers to itself, it will go into an infinite loop trying to generate the decompiled source.