문서를 영문으로 보려면 영문 확인란을 선택하세요. 마우스 포인터를 텍스트 위로 이동시켜 팝업 창에서 영문 텍스트를 표시할 수도 있습니다.
번역
영문

Team Foundation용 클라이언트 개체 모델을 사용하여 여러 형식의 작업 항목에 대한 코드 작성

다른 팀 프로젝트에 대 한 코드를 작성 하는 경우 다른 비슷한 용도로 사용 되는 작업 항목의 형식에 같은 함수를 수행할 수 있습니다. 이러한 형식은 다른 프로세스 템플릿에서 온다 또는 팀을이 특정 팀 프로젝트에 대해 사용자 지정한 수 있기 때문에 달라질 수 있습니다. 사용자 스토리 및 어떤 고객 요구 모두를 나타내야 요구 사항 및 값에서 동일한 기능을 수행 하는 경우를 생각해 보겠습니다. 각 형식의 작업 항목에 대 한 별도 코드를 작성 하는 대신 코드를 모두 하 일반화할 수 있습니다. 또한 한 팀 팀원이 작업 스토리 포인트에서 대신 시간에서 예측할 수 있도록 작업 항목 정의 대 한 사용자 스토리 사용자 지정한 수 있습니다. 기본 및 사용자 지정된 전략 모두 처리 하도록 코드를 조정 하 여 자신의 노력을 복제를 방지할 수 있습니다.

이 항목은 아직 정의 된 작업 항목에서 특정 유형의 작업을 수행 하는 코드 예제를 찾을 수 및 특정 유형의 사용자 지정을 지원 하도록 해당 코드를 리팩터링 하는 방법을 알아봅니다. 작업 항목 형식을 사용자 지정 하는 방법에 대 한 자세한 내용은 Visual Studio TFS에서 구성 및 사용자 지정할 수 있는 작업에 대한 종단 간 뷰.

항목 내용

이 코드 샘플에서는 각 팀 프로젝트에서 모든 사용자 스토리 나무 서버에 인쇄 및 자식이 각 스토리에 대 한 추정치를 포함 합니다. 이 샘플을 사용 하려면 콘솔 응용 프로그램 만들기에서 다음 어셈블리 참조 추가 및 다음 Program.cs (또는 Module1.vb)의 내용을 다음 코드로 바꿉니다.

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;
        }
    }
}

이 샘플에서는 스토리 포인트 필드 또는 초기 작업 시간 필드가 각 작업 항목을 사용 하는지 여부를 확인 하 고 해당 필드에서 예상 인쇄 하려면 PrintTrees 메서드를 수정 합니다. 이 샘플을 사용 하려면 줄을 바꿀 Console.WriteLine(target.Fields["Story Points"].Value); PrintTrees 메서드에 다음 코드를 사용 합니다.

// 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); 

동일 하거나 비슷한 목적으로 다른 팀 프로젝트에 사용 되는 작업 항목의 서로 다른 범주로 그룹화 할 수 있습니다. 범주에 속한 모든 작업 항목에 동일한 기능을 수행 하는 코드를 작성할 수 있습니다. 이 샘플에서는 모든 사용자 스토리, 요구 사항 및 제품 백로그 항목 요구 사항 범주의 작업 항목의 형식에 대 한 추정치를 인쇄합니다.

이 샘플을 사용 하려면 앞의 예제에서 Main 함수를 다음 코드로 바꿉니다.

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); 
    }
}
표시: