ActionContainer is an implementation of the Service Agent pattern in written in C#. It takes advantage of the C# 4.0 dynamic feature to eliminate cluttering your code with empty message classes and also manipulate calls at runtime.
Usage of ActionContainer is straight forward. Start by creating a class that
implements the empty
IActionProvider interface with public methods.
Inject an instance of the ServiceAgent class, and make calls to the registered methods
SayHello with a string, will look up a registered method with the name
SayHello, takes a string argument, and has a void return type. Same behavior
GeneratePassword, except it returns a string.
Looking up methods by name and parameters doesn’t require creating a class (think SayHelloRequest) for each registered action.
The ServiceAgent is also return type aware. In the call
string password =
ServiceAgent.GeneratePassword();, a search is done for the GeneratePassword
that returns string. In this case, the
SimpleProvider has the only registered
GeneratePassword. Lets say we added another provider, the
Now calls to
ServiceAgent.GeneratePassword(); can handle both int and string
return types with no special PasswordResponse or NumericPasswordResponse
The default method lookup ability of ActionContainer is just that: the default.
ActionContainer provides a hook into its resolving process simply by creating
implementations of the
CanHandle method returns true if it has an opinion on the return value
of a call. If
CanHandle is true,
Handle allows the object to manipulate the
return value a value.
ActionCallInfo includes the method name, named parameters, unnamed
parameters, and expected return type.
Using this information you could add helpful hooks such as a
LogListener will watch for an argument named log with the value of
true. It will then write to the console the name of the call, return type, and
arguments. To put it to use, just use the ServiceAgent as follows:
Because the ServiceAgent is a dynamic object, any number of named arguments can be passed to its method calls.
Another possible hook would be a
StringTrimListener. Any arguments that are strings
can be trimmed before getting passed to the handling method.
No change in code is needed to have calls to the ServiceAgent start using the
StringTrimListener. Just make a call on something with a string with hanging
ActionContainer has some requirements that you must keep in mind while using it. Most deal with determining types.
First, when doing variable assignment you must explicitly provide the type when
returning values. Using
var will result in unfriendly behavior.
Second, passing null values as parameters limits lookup. This has to do with null not carrying any type information other than object.
Finally, ActionContainer is slow (~10x) compared to direct method calls. Using it in a long running loop will have noticeable performance hits. However, in response to user actions, incoming web request, etc, the difference is negligible.
It’s on Github. Go and grab it with Git.
$ git clone git://github.com/statianzo/ActionContainer.git
13 Aug 2010