Pour afficher l’article en anglais, activez la case d’option Anglais. Vous pouvez aussi afficher la version anglaise dans une fenêtre contextuelle en faisant glisser le pointeur de la souris sur le texte.
Traduction
Anglais

Écrire du code pour différents types d'éléments de travail à l'aide du Modèle d'objet client pour Team Foundation

Lorsque vous écrivez du code pour des projets d'équipe, vous pouvez remplir la même fonction sur différents types d'éléments de travail qui répondent aux objectifs semblables. Ces types peuvent être différents parce qu'ils proviennent de différents modèles de processus, ou une équipe peut les être personnalisés pour un projet d'équipe spécifique. Par exemple, vous pouvez remplir la même fonction de les récits utilisateur et des spécifications, qui doivent représenter les clients requièrent et évaluent. Au lieu de code distinct d'écriture pour chaque type d'élément de travail, vous pouvez généraliser votre code fonctionne pour les deux. En outre, une équipe peut avoir personnalisé la définition d'élément de travail pour les récits utilisateur afin que les membres de l'équipe puissent estimer le travail en heures et non à des points de récit. Vous pouvez éviter de dupliquer votre propre travail en ajustant votre code pour gérer la valeur par défaut et les stratégies personnalisées.

Dans cette rubrique, vous trouverez un exemple de code qui effectue une tâche sur un type spécifique d'élément de travail qui n'a pas été personnalisé, puis vous explique comment refactoriser le code pour prendre en charge certains genres de personnalisations. Pour plus d'informations sur la personnalisation de types d'éléments de travail, consultez Une perspective complète de ce que vous pouvez configurer et personnaliser dans Visual Studio TFS.

Dans cette rubrique

Cet exemple de code imprime les arborescences de tous les récits utilisateur dans chaque projet d'équipe sur un serveur et inclut des estimations pour chaque récit qui n'a aucun enfant. Pour utiliser cet exemple, vous créez une application console, ajoutez des références aux assemblys suivants, puis remplacez le contenu (Program.cs ou Module1.vb) par le code suivant.

using System;
using System.Text;
using System.Collections.ObjectModel;
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.Framework.Client;
using Microsoft.TeamFoundation.Framework.Common;
using Microsoft.TeamFoundation.WorkItemTracking.Client;

namespace Microsoft.TeamFoundation.SDK
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                // Connect to Team Foundation Server. The form of the url is http://server:port/vpath.
                //     Server - the name of the server that is running the application tier for Team Foundation.
                //     port - the port that Team Foundation uses. The default port is 8080.
                //     vpath - the virtual path to the Team Foundation application. The default path is tfs.
                TfsConfigurationServer configurationServer =
                    TfsConfigurationServerFactory.GetConfigurationServer(new Uri("http://Server:8080/tfs"));
               
                // Get the catalog of team project collections
                CatalogNode catalogNode = configurationServer.CatalogNode;
                ReadOnlyCollection<CatalogNode> tpcNodes = catalogNode.QueryChildren(
                    new Guid[] { CatalogResourceTypes.ProjectCollection }, false, CatalogQueryOptions.None);

                // Process each team project collection
                foreach (CatalogNode tpcNode in tpcNodes)
                {
                    // Use the InstanceId property to get the team project collection
                    Guid tpcId = new Guid(tpcNode.Resource.Properties["InstanceId"]);
                    TfsTeamProjectCollection tpc = configurationServer.GetTeamProjectCollection(tpcId);

                    // Get the work item store
                    WorkItemStore wiStore = tpc.GetService<WorkItemStore>();

                    // Query for the trees of active user stories in the team project collection
                    StringBuilder queryString = new StringBuilder("SELECT [System.Id] FROM WorkItemLinks WHERE ");
                    queryString.Append("([Source].[System.WorkItemType] = 'User Story' AND [Source].[System.State] = 'Active') AND ");
                    queryString.Append("([System.Links.LinkType] = 'System.LinkTypes.Hierarchy-Forward') And ");
                    queryString.Append("([Target].[System.WorkItemType] = 'User Story' AND [Target].[System.State] = 'Active') ORDER BY [System.Id] mode(Recursive)");
                    Query wiQuery = new Query(wiStore, queryString.ToString());
                    WorkItemLinkInfo[] wiTrees = wiQuery.RunLinkQuery();

                    // Print the trees of user stories, with the estimated sizes of each leaf
                    PrintTrees(wiStore, wiTrees, "    ", 0, 0);
                }
            }

            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }
        }

        // Each WorkItemLinkInfo structure in the collection contains the IDs of the linked work items.
        // In this case, the sourceId is the ID of the user story that is on the parent side of the link, and
        // the targetId is the ID of the user story that is on the child side of the link. The links
        // are returned in depth-first order. This function recursively traverses the collection
        // and the title of each user story. If the user story has no children, its estimation is also printed.
        static int PrintTrees(WorkItemStore wiStore, WorkItemLinkInfo[] wiTrees, string prefix, int sourceId, int iThis)
        {
            int iNext = 0;

            // Get the parent of this user story, if it has one
            WorkItem source = null;
            if (sourceId != 0)
            {
                source = wiStore.GetWorkItem(wiTrees[iThis].SourceId);
            }

            // Process the items in the list that have the same parent as this user story
            while (iThis < wiTrees.Length && wiTrees[iThis].SourceId == sourceId)
            {
                // Get this user story
                WorkItem target = wiStore.GetWorkItem(wiTrees[iThis].TargetId);
                Console.Write(prefix);
                Console.Write(target.Type.Name);
                Console.Write(": ");
                Console.Write(target.Fields["Title"].Value);
                if (iThis < wiTrees.Length - 1)
                {
                    if (wiTrees[iThis].TargetId == wiTrees[iThis + 1].SourceId)
                    {
                        // The next item is this user story's child. Process the children
                        Console.WriteLine();
                        iNext = PrintTrees(wiStore, wiTrees, prefix + "    ", wiTrees[iThis + 1].SourceId, iThis + 1);
                    }
                    else
                    {
                        // The next item is not this user story's child.
                        Console.Write("; estimate = ");
                        Console.WriteLine(target.Fields["Story Points"].Value);
                        iNext = iThis + 1;
                    }
                }
                else
                {
                    // This user story is the last one.
                    iNext = iThis + 1;
                }

                iThis = iNext;
            }

            return iNext;
        }
    }
}

Cet exemple modifie la méthode de PrintTrees pour déterminer si chaque élément de travail utilise les points de récit champ ou le champ de travail de ligne de base et imprimer l'évaluation de ce champ. Pour utiliser cet exemple, remplacez la ligne Console.WriteLine(target.Fields["Story Points"].Value); dans la méthode de PrintTrees par le code suivant.

// Determine which estimation field is present
string fieldName = "Story Points";
if (target.Type.FieldDefinitions.TryGetByName(fieldName) == null) 
{
    fieldName = "Baseline Work";
}
Console.WriteLine(target.Fields[fieldName].Value); 

Vous pouvez regrouper en différentes catégories de types d'éléments de travail qui atteignent le même ou objectifs semblables dans différents projets d'équipe. Vous pouvez écrire le code pour remplir la même fonction sur tous les éléments de travail qui appartiennent à une catégorie. Cet exemple imprime les estimations pour tout type d'élément de travail dans la catégorie de spécifications, telles que les récits utilisateur, spécifications, et des éléments du journal des travaux en souffrance (backlog) du produit.

Pour utiliser cet exemple, remplacez la fonction Main de l'exemple précédent par le code suivant.

static void Main(string[] args) 
{
    try
    {
        // Connect to Team Foundation Server. The form of the url is http://server:port/vpath.
        //     server - the name of the server that is running the application tier for Team Foundation.
        //     port - the port that Team Foundation uses. The default ort is 8080.
        //     vpath - the virtual path to the Team Foundation application. The default path is tfs. 
        TfsConfigurationServer configurationServer =
            TfsConfigurationServerFactory.GetConfigurationServer(new Uri("http://server:8080/tfs"));

        // Get the catalog of team project collections
        CatalogNode catalogNode = configurationServer.CatalogNode; 
        ReadOnlyCollection<CatalogNode> tpcNodes = catalogNode.QueryChildren(
            new Guid[] { CatalogResourceTypes.ProjectCollection }, false, CatalogQueryOptions.None); 

        // Process each team project collection
        foreach (CatalogNode tpcNode in tpcNodes) 
        {
            // Use the InstanceId property to get the team project collection
            Guid tpcId = new Guid(tpcNode.Resource.Properties["InstanceId"]);
            TfsTeamProjectCollection tpc = configurationServer.GetTeamProjectCollection(tpcId); 

            // Get the work item store
            WorkItemStore wiStore = tpc.GetService<WorkItemStore>();
            foreach (Project project in wiStore.Projects)
            {
                Console.Write("Project: ");
                Console.WriteLine(project.Name); 

                // Get the type of work item to use 
                CategoryCollection categories = wiStore.Projects[project.Name].Categories; 
                string wiType = categories["Requirement Category"].DefaultWorkItemType.Name;

                // Query for the trees of active user stories in the team project collection
                StringBuilder queryString = new StringBuilder("SELECT [System.Id] FROM WorkItemLinks WHERE ");
                queryString.Append("([Source].[System.WorkItemType] = '"); 
                queryString.Append(wiType); 
                queryString.Append("' AND [Source].[System.TeamProject] = '"); 
                queryString.Append(project.Name);
                queryString.Append("') AND ");
                queryString.Append("([System.Links.LinkType] = 'System.LinkTypes.Hierarchy-Forward') And ");
                queryString.Append("([Target].[System.WorkItemType] = 'User Story'  AND  ");
                queryString.Append("[Target].[System.State] = 'Active') ORDER BY [System.Id] mode(Recursive)"); 
                Query wiQuery = new Query(wiStore, queryString.ToString());
                WorkItemLinkInfo[] wiTrees = wiQuery.RunLinkQuery();

                // Print the trees of user stories and requirements, with the estimated size of each leaf

                PrintTrees(wiStore, wiTrees, "    ", 0, 0); 
            }
        }
    }

    catch (Exception e) 
    {
        Console.WriteLine(e.Message); 
    }
}
Afficher: