Showing posts with label Action. Show all posts
Showing posts with label Action. Show all posts

Tuesday, 10 April 2012

Actions and Funcs (part 2).....Action as Builder

Following on from my last post about Actions, Predicates, and Funcs; I want to provide an example of one place that I've seen a framework successfully use an Action as in an API.  Recently, I've been doing some work with NServiceBus (NSB).  NSB gives a nice terse way to Send or Publish a new message.  It looks like this:


This code uses an Action<T> underneath to create a new instance of the type that is going to be sent or published.  What is extra cool about this is that NSB allows you to define values for properties of an instance that it will dynamically generate.  Like the example above, this allows NSB to give the impression that it can assign values directory to interface properties!

So, how can we allow users of our API to define properties, but keep hold of the specifics about how we create an object?

Action<T> as Builder
Like NSB, we can take in an Action<T> and allow the user of the API to build the object they desire.  To show the specifics of how to do this, I'll complete a non-production version of what NSB does.  So, first we need to define the IBus interface:


And this is a simple implementation for IBus:



A bit of explanation
So, it turns out that the code is quite simple for a pretty cool API feature.  The implementation of IBus only needs to understand the type of the message, then can create a blank instance, and pass the instance to the action for building.  At this point, the action implementation (defined in the method call to IBus.Publish<T>) takes over and fills in all the properties.  This works because T has to be an IMessage (which means it must be a reference type). Nice.  Using this type of technique would also allow the framework code to make a default instance (with some properties set) and let these values to be changed during the action implementation.

More to come...

Thursday, 29 March 2012

Actions and Funcs

For a long time now, I have been wanting to better understand Action<T>, Func<T1, T2>, and Predicate<T> in C#.  I have always understood that they are generic delegates, but I never could get where they are most appropriate to be used when designing a library or framework for other developers to use.  I did see examples in libraries like linq, AutoMapper, and RhinoMocks where I thought the usage of Actions or Funcs as extension points made a lot of sense.

So, with this in mind, I'm planning to devote a couple of posts about an exploration into Action<T>, Func<T1, T2>, and Predicate<T>.  Hopefully, by recording this journey I'll take more from it and even perhaps help a few other developers to better embrace these tools.

What?
In this post, I just want to do a quick introduction to what Action<T>, Func<T1, T2>, and Predicate<T> are.  As I mentioned, these classes seem to be just another way to express a delegate in C#.  So why are they needed?  There seem to be many answers to that question.  First off, they allow for lambda expressions in C#, they are much more terse than anonymous delegates, and in my opinion they express a function pointer in a more direct way than a traditional delegate.  Plus, they are fun and make code more expressive.

Action<T>, Func<T1, T2>, Predicate<T> and delegates for that matter are just function pointers.  They allow functions to be passed around in code as data.

Events
The place where most people have seen this the most is with C# events.  An event needs a delegate type in order to know what type of function it can register.  Then when you register that OnLoad event for example, the compiler will only allow a callback method to register against the event that conforms to the correct signature.




In the above example, we are defining a delegate with the common .NET event signature void (object sender, EventArgs e). This comes in handy when we want to wire up a callback function that will listen out for when the event fires.  Underneath, the complier is going to make a new collection of OnLoadHandler delegate types and add (+=) or remove (-=) callbacks from the collection.  Then when the event is fired, the collection will iterate and call all the registered functions.


So, events is one place that many developers are familiar with delegates.  Since Action<T> is a void returning generic delegate, can we use it instead.  Yes, and here is the code:



As you can see, we have eliminated the need for a delegate to be defined in the Page class.  And what is better, we got rid of that Page.OnLoadHandler scoping issue when we registered the event.  The Action<T> can be registered against the event and all the functions stay roughly the same.  This is pretty cool, however, with EventHandler<T> out there not that useful.  This is more of an example to get warmed up for more to come.

Alright, got it
It's easy to see what is going on here.  Action<T> allows us a better way to express a delegate.  So now it's time to define these guys.

Action<T>
Actions are delegates that always return void.  Each generic type defined (and in the same order) become the type of the parameter in the function.

Func<T1, T2>
Funcs are the most expressive generic delegate form.  They take at least two generic type arguments because the last one is always the return type of the delegate signature.  So, in this case T2 is the type that you want to return.

Predicate<T>
Predicates are Funcs that always return a boolean value.  All of Predicate's generic type arguments define the parameters in its delegate signature.

In the next post, I'll dig a bit deeper into some more typical usages for API design.  See ya then!