HOW TO: Writing Custom Tasks - Part II - Types and Task Parameters

In Part I of the series on writing custom tasks, I covered the basic mechanics behind implementing your own custom task.  And I had promised that I'd cover the details on the types of task parameters that are supported today.  So here we go.

The simplest and most straightforward "type" for a task parameter is what I already covered in my previous post - i.e. String type.  But what if I really wanted to define a property like shown below?

   public DateTime BuildDate
{
get { return buildDate; }
set { buildDate = value; }
}

Well - believe it or not, this works today.  This is how you would use such a property:

   <SomeTaskThatLabelsSourceSafe BuildDate="15-Jun-2005" ….>

What this essentially means is that within the task, you will have a true DateTime object that represents the date you passed in via the project file.  Useful, isn't it?

Here are the various data types that you can use for defining properties today. 

  • Boolean
  • Byte
  • Char
  • Decimal
  • Double
  • Int16
  • Int32
  • Int64
  • SByte
  • Single
  • String
  • UInt16
  • UInt32
  • UInt64

These types work well - especially if you are dealing with single value / non - structured task parameters. What if you wanted representation that is a bit more richer?  Metadata is what I am thinking about here - and metadata is the single most coolest aspect of "items" in MSBuild.

So, here's a quick refresher: Metadata is defined on items as shown below. I have a single piece of metadata called Artist on an item that represents an mp3 file:

   <ItemGroup>
<MP3 Include="BlackDog.mp3">
<Artist>Led Zeppelin</Artist>
</MP3>
</ItemGroup>
 
In order for a task to be able to effectively deal with items, simply define the task parameter type as ITaskItem.  Here's an example:

   public ITaskItem MusicFile
{
get { return mp3File; }
set { mp3File = value; }
}

Defining a task parameter as ITaskItem allows you to use methods such as GetMetadata, SetMetadata, RemoveMetadata on mp3File, within the code for the custom task.

So how do I pass an item into a task that supports this task parameter?  Once again pretty straightforward - without any bearing on the actual type of the task parameter itself.  What's shown below works regardless of whether MusicFile is defined as ITaskItem or string or any other type we have discussed so far.

   <PlayMusic MusicFile="@(MP3)" />

Also, you don't necessarily have to use a pre-defined item to pass into the task.  MSBuild is capable of dealing with verbatim strings as values for ITaskItem type of parameters - as shown:

   <PlayMusic MusicFile="BlackDog.mp3" />
 
The final aspect of data types that I'd like to cover is idea of item collections. 

Supporting collections in your task parameter is simply a matter of defining your task parameter as an array of any of the types we have discussed so far.  So ITaskItem[] would be the choice if you wanted to deal with more than one mp3 file in the last example.

Invoke the task and pass in multiple items like this:

   <!-- MP3File contains more than one song -->
<PlayMusic MusicFiles="@(MP3File)" />

Alternatively, you can pass in more than one item verbatim like this:

   <PlayMusic MusicFiles="BlackDog.mp3;ZooStation.mp3" />

That's about it for Part II :)  Do tell us how we can improve on these posts.  If you would like me to cover any specific aspects that I have not discussed already, just holler and I'll be sure to write about it.

[ Author: Faisal Mohamood ]