0

Given a build definition, I extract the following pieces from it:

m_template = (DynamicActivity)WorkflowHelpers.DeserializeWorkflow(buildDefinition.Process.Parameters);
Properties = m_template.Properties.ToDictionary(p => p.Name, StringComparer.OrdinalIgnoreCase);
Metadata = WorkflowHelpers.GetCombinedMetadata(m_template).ToDictionary(m => m.ParameterName);
m_parameters = WorkflowHelpers.DeserializeProcessParameters(buildDefinition.ProcessParameters)

Now I wish to know the value of an arbitrary process parameter.

My current code is:

public ParameterValue GetParameterValue(string name)
{
    object propValue;
    var valueType = GetParameterType(name, out propValue);

    object value;
    if (!m_parameters.TryGetValue(name, out value))
    {
        value = propValue;
    }

    return new ParameterValue(valueType, value);
}

private Type GetParameterType(string name, out object value)
{
    value = null;
    if (Properties != null)
    {
        DynamicActivityProperty property;
        if (Properties.TryGetValue(name, out property))
        {
            var inArgument = property.Value as InArgument;
            if (inArgument != null)
            {
                if (inArgument.Expression != null)
                {
                    var exprString = inArgument.Expression.ToString();
                    if (!exprString.StartsWith(": VisualBasicValue<"))
                    {
                        value = exprString;
                    }
                }
                return inArgument.ArgumentType;
            }
            if (property.Value != null)
            {
                value = property.Value;
                return property.Value.GetType();
            }
            var typeName = property.Type.ToString();
            if (typeName.StartsWith(IN_ARGUMENT_TYPE_NAME_PREFIX))
            {
                typeName = typeName.Substring(IN_ARGUMENT_TYPE_NAME_PREFIX.Length, typeName.Length - IN_ARGUMENT_TYPE_NAME_PREFIX.Length - 1);
                return Type.GetType(typeName, true);
            }
            return property.Type;
        }
    }

    return typeof(string);
}

Unfortunately, this code stumbles for parameters satisfying all of the following conditions:

  • The parameter value is wrapped as InArgument<T>.
  • T is a non primitive type, for example string[]
  • The build definition does not override the value inherited from the process template.

What happens is that:

  1. Because the value is non primitive exprString.StartsWith(": VisualBasicValue<") and I do not know how to handle it. Hence propValue is null.
  2. Because the value is not overridden by the build definition !m_parameters.TryGetValue(name, out value) and hence I just return propValue.

As a result my logic returns null. But it is wrong! For example, I have a string[] parameter which has a list of string in the process template, but my logic returns null for the reasons explained.

So, what is the proper way to compute it?

mark
  • 59,016
  • 79
  • 296
  • 580

1 Answers1

0

You can use the following code (included in another link) to get value and type of one process parameter:

  TfsTeamProjectCollection tfctc = new TfsTeamProjectCollection(new Uri("http://tfsservername:8080/tfs/DefaultCollection"));
        IBuildServer bs = tfctc.GetService<IBuildServer>();

        IBuildDetail[] builds = bs.QueryBuilds("teamprojectname", "builddefinitionname");
        foreach (var build in builds)
        {
            var buildefinition = build.BuildDefinition;
            IDictionary<String, Object> paramValues = WorkflowHelpers.DeserializeProcessParameters(buildefinition.ProcessParameters);
            string processParametersValue = paramValues["argument1"].ToString();
            Console.WriteLine(processParametersValue);
        }

Also have a check on this case: TFS 2010: Why is it not possible to deserialize a Dictionary<string, object> with XamlWriter.Save when I can use XamlReader for deserializing

Community
  • 1
  • 1
Vicky - MSFT
  • 4,970
  • 1
  • 14
  • 22