In my previous posts, we discussed…

  1. Custom Process Parameters
  2. Process Parameter Metadata
  3. Custom Editors

In this post, I want to continue this discussion of process parameters and explain how to use your own custom types for process parameters. Previously, we used a String version number (i.e. “Beta2.0.30111.12”). But what if we would like to do something in our build based on part of the version number. For instance, we may want to deploy the first build for each day (i.e. revision number = 0). That would be very difficult with just a string. It would be easier if we stored the bits of the version number (Major, Minor, Date, and Revision). So let’s change our implementation!

Here is my VersionInfo class:

using System;

namespace CustomWorkflowTypes
{
    public class VersionInfo
    {
        public String Major { get; set; }
        public int Minor { get; set; }
        public int Date { get; set; }
        public int Revision { get; set; }

        public override string ToString()
        {
            return String.Format("{0}.{1}.{2}.{3}", Major, Minor, Date, Revision);
        }
    }
}

I also changed the dialog to use this new class:

using System;
using System.Windows.Forms;

namespace CustomWorkflowTypes
{
    public partial class SimpleVersionDialog : Form
    {
        public SimpleVersionDialog()
        {
            InitializeComponent();
        }

        public VersionInfo Version
        {
            get
            {
                return new VersionInfo()
                {
                    Major = textMajor.Text,
                    Minor = int.Parse(textMinor.Text),
                    Date = int.Parse(textDate.Text),
                    Revision = int.Parse(textRevision.Text)
                };
            }
            set
            {
                textMajor.Text = value.Major;
                textMinor.Text = value.Minor.ToString();
                textDate.Text = value.Date.ToString();
                textRevision.Text = value.Revision.ToString();
            }
        }
    }
}

A simple one line change to the SimpleVersionEditor class passes the new type to the dialog:

dialog.Version = value as VersionInfo;

And here is the XAML with a simple change to the type of the VersionNumber property:

<Activity x:Class="TfsBuild.Process" 
  xmlns="http://schemas.microsoft.com/netfx/2009/xaml/activities" 
  xmlns:mtbc="clr-namespace:Microsoft.TeamFoundation.Build.Client;assembly=Microsoft.TeamFoundation.Build.Client" 
  xmlns:mtbw="clr-namespace:Microsoft.TeamFoundation.Build.Workflow;assembly=Microsoft.TeamFoundation.Build.Workflow" 
  xmlns:mtbwa="clr-namespace:Microsoft.TeamFoundation.Build.Workflow.Activities;assembly=Microsoft.TeamFoundation.Build.Workflow" 
  xmlns:c="clr-namespace:CustomWorkflowTypes;assembly=CustomWorkflowTypes" 
  xmlns:s="clr-namespace:System;assembly=mscorlib" 
  xmlns:mva="clr-namespace:Microsoft.VisualBasic.Activities;assembly=System.Activities" 
  xmlns:this="clr-namespace:TfsBuild;" 
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
  <x:Members>
    <x:Property Name="VersionNumber" Type="InArgument(c:VersionInfo)" />
    <x:Property Name="Verbosity" Type="InArgument(mtbw:BuildVerbosity)" />
    <x:Property Name="Metadata" Type="mtbw:ProcessParameterMetadataCollection" />
    <x:Property Name="SupportedReasons" Type="mtbc:BuildReason" />
  </x:Members>
  <this:Process.Verbosity>[Microsoft.TeamFoundation.Build.Workflow.BuildVerbosity.Normal]</this:Process.Verbosity>
  <this:Process.Metadata>
    <mtbw:ProcessParameterMetadataCollection>
      <mtbw:ProcessParameterMetadata 
            Category="Basic" 
            Description="The Version number of the build." 
            DisplayName="Version Number"
            Editor="CustomWorkflowTypes.SimpleVersionEditor,CustomWorkflowTypes"
            ParameterName="VersionNumber" />
    </mtbw:ProcessParameterMetadataCollection>
  </this:Process.Metadata>
  <this:Process.SupportedReasons>All</this:Process.SupportedReasons>
  <mva:VisualBasic.Settings>Assembly references and imported namespaces serialized as XML namespaces</mva:VisualBasic.Settings>
  <Sequence>
    <mtbwa:WriteBuildMessage DisplayName="Version Number" Message="[VersionNumber.ToString()]" Importance="High" />
  </Sequence>
</Activity>

You may have also noticed the VisualBasic settings lines that I added. Those are needed so that the expression in the Message attribute can be evaluated by the Visual Basic Engine.

And that’s it. You just have to build it and deploy it like you did last time. Note that if a client can’t resolve the custom type, an error will appear to the user when they edit the definition.

That ends this series on Process Parameters. At least for now!