Schreiben von Code für verschiedene Arbeitsaufgabentypen unter Verwendung des Clientobjektmodells für Team Foundation
Wenn Sie Code für verschiedene Teamprojekte schreiben, können Sie die gleiche Aufgabe auf verschiedenen Typen von Arbeitsaufgaben ausführen, die ähnliche Zwecken dienen. Diese Typen sind möglicherweise anders, da sie von den verschiedenen Prozessvorlagen stammen, oder ein Team gepasst sie möglicherweise für ein bestimmtes Teamprojekt an. Beispielsweise können Sie die gleiche Aufgabe von User Storys und Anforderungen ausführen, sollten die darstellen, welche Kunden benötigen und bewerten. Anstatt Code zum Schreiben für jeden Arbeitsaufgabentyp, können Sie den Code generalisieren, um für beide zu arbeiten. Außerdem gepasst kann ein Team die Arbeitsaufgabendefinition für User Storys an, damit Teammitglieder Arbeit in Stunden anstelle der Story Points schätzen können. Sie können den eigenen, Aufwand zu duplizieren vermeiden, indem Sie den Code anpassen, um den standardmäßigen und benutzerdefinierten Strategien zu behandeln.
In diesem Thema können Sie ein Codebeispiel finden, das eine Aufgabe auf einem bestimmten Arbeitsaufgabentyp ausführt, die nicht angepasst wurde, und dann können Sie erfahren, wie dieser Code umgestaltet, um bestimmte Arten von Anpassungen zu unterstützen. Weitere Informationen darüber, wie die Typen von Arbeitsaufgaben, finden Sie unter Eine End-to-End-Ansicht der in Visual Studio TFS konfigurierbaren und anpassbaren Elemente angepasst wird.
In diesem Thema
Drucken Sie Strukturen von User Storys mit Schätzungen in den Story Points
Drucken Sie Strukturen von User Storys mit Schätzungen entweder in den Story Points oder in der Geplante Arbeit
Drucken Sie Strukturen von Arbeitsaufgaben, die als Anforderungen mit Schätzungen verwendet werden
Drucken Sie Strukturen von User Storys mit Schätzungen in den Story Points
Dieses Codebeispiel gibt Strukturen aller User Storys in jedem Teamprojekt auf einem Server und schließt Schätzungen für jeden Textabschnitt ein, die nicht über untergeordnete Elemente verfügt. Um dieses Beispiel zu verwenden, erstellen Sie eine Konsolenanwendung, fügen Verweise auf die folgenden Assemblys hinzu und ersetzen dann den Inhalt Program.cs (oder Module1.vb) durch den folgenden Code.
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("https://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;
}
}
}
Imports System
Imports System.Text
Imports System.Collections.ObjectModel
Imports Microsoft.TeamFoundation.Client
Imports Microsoft.TeamFoundation.Framework.Client
Imports Microsoft.TeamFoundation.Framework.Common
Imports Microsoft.TeamFoundation.WorkItemTracking.Client
Module Module1
Sub Main(ByVal sArgs() As String)
Try
' Connect to the 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 is tfs.
Dim tfsUri As New Uri("https://Server:8080/tfs")
Dim configurationServer As TfsConfigurationServer
configurationServer = TfsConfigurationServerFactory.GetConfigurationServer(tfsUri)
' Get the catalog of team project collections
Dim catalogNode As CatalogNode
catalogNode = configurationServer.CatalogNode
Dim tpcNodes As ReadOnlyCollection(Of CatalogNode)
Dim gVar As Guid() = New Guid() {CatalogResourceTypes.ProjectCollection}
tpcNodes = catalogNode.QueryChildren(gVar, False, CatalogQueryOptions.None)
' Process each team project collection
For Each tpcNode In tpcNodes
Dim tpcGuid As Guid = New Guid(tpcNode.Resource.Properties("InstanceID"))
Dim tpc As New TfsTeamProjectCollection(tfsUri)
tpc = configurationServer.GetTeamProjectCollection(tpcGuid)
' Get the work item store
Dim wiStore As WorkItemStore
wiStore = tpc.GetService(Of WorkItemStore)()
' Query for the trees of active user stories in the team project collection
Dim queryString As 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)")
Dim wiQuery As New Query(wiStore, queryString.ToString())
Dim wiTrees() As WorkItemLinkInfo
wiTrees = wiQuery.RunLinkQuery()
' Print the trees of user stories with the estimated size of each leaf.
PrintTrees(wiStore, wiTrees, " ", 0, 0)
Next
Catch ex As Exception
Console.WriteLine(ex.Message)
End Try
End Sub
' 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.
Function PrintTrees(ByVal wiStore As WorkItemStore, ByVal wiTrees As WorkItemLinkInfo(), ByVal prefix As String, ByVal sourceId As Integer, ByVal iThis As Integer) As Integer
Dim iNext As Integer = 0
' Get the parent of this user story, if it has one
Dim source As WorkItem = Nothing
If sourceId <> 0 Then
source = wiStore.GetWorkItem(wiTrees(iThis).SourceId)
End If
' Process the items in the list that have the same parent as this user story
While (iThis < wiTrees.Length AndAlso wiTrees(iThis).SourceId = sourceId)
' Get this user story
Dim target As 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) Then
If wiTrees(iThis).TargetId = wiTrees(iThis + 1).SourceId Then
' The next item is the user story's child.
Console.WriteLine()
iNext = PrintTrees(wiStore, wiTrees, prefix + " ", wiTrees(iThis + 1).SourceId, iThis + 1)
Else
' The next item is not the user story's child
Console.Write("; estimate = ")
Console.WriteLine(target.Fields("Story Points").Value)
iNext = iThis + 1
End If
Else
' This user story is the last one.
iNext = iThis + 1
End If
iThis = iNext
End While
Return iNext
End Function
End Module
Drucken Sie Strukturen von User Storys mit Schätzungen entweder in den Story Points oder in der Geplante Arbeit
In diesem Beispiel wird die PrintTrees-Methode, um die Schätzung von diesem Feld zu bestimmen, ob jede Arbeitsaufgabe das Story Point-Feld verwendet oder das Baselinearbeitsfeld und drucken. Um dieses Beispiel zu verwenden, ersetzen Sie die Zeile Console.WriteLine(target.Fields["Story Points"].Value); in der PrintTrees-Methode durch den folgenden Code.
// 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);
Dim fieldName As String
fieldName = "Story Points"
If (target.Type.FieldDefinitions.TryGetByName(fieldName) Is Nothing) Then
fieldName = "Baseline Work"
End If
Console.WriteLine(target.Fields(fieldName).Value)
Drucks-Strukturen aller Arbeitsaufgaben in einer Kategorie
Sie können in Kategorien verschiedene Arbeitsaufgabentypen gruppieren, die gleiche oder ähnliche Zwecke in anderen Teamprojekten dienen. Sie können Code schreiben, um die gleiche Aufgabe auf allen Arbeitsaufgaben auszuführen, die einer Kategorie angehören. Dieses Beispiel gibt Schätzungen für jeden Arbeitsaufgabentyp in der Anforderungskategorie, wie User Storys, Anforderungen und Produktrückstandselementen.
Um dieses Beispiel zu verwenden, ersetzen Sie die Hauptfunktion des vorherigen Beispiel durch den folgenden Code.
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("https://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);
}
}
Sub Main(ByVal sArgs() As String)
Try
' Connect to the 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 is tfs.
Dim tfsUri As New Uri("https://server:8080/tfs")
Dim configurationServer As TfsConfigurationServer
configurationServer = TfsConfigurationServerFactory.GetConfigurationServer(tfsUri)
' Get the catalog of team project collections
Dim catalogNode As CatalogNode
catalogNode = configurationServer.CatalogNode
Dim tpcNodes As ReadOnlyCollection(Of CatalogNode)
Dim gVar As Guid() = New Guid() {CatalogResourceTypes.ProjectCollection}
tpcNodes = catalogNode.QueryChildren(gVar, False, CatalogQueryOptions.None)
' Process each team project collection
For Each tpcNode In tpcNodes
Dim tpcGuid As Guid = New Guid(tpcNode.Resource.Properties("InstanceID"))
Dim tpc As New TfsTeamProjectCollection(tfsUri)
tpc = configurationServer.GetTeamProjectCollection(tpcGuid)
' Get the work item store
Dim wiStore As WorkItemStore
wiStore = tpc.GetService(Of WorkItemStore)()
' Query for the trees of active user stories in the team project collection
Dim project As Project
For Each project In wiStore.Projects
Console.Write("Project: ")
Console.WriteLine(project.Name)
' Get the type of work item to use
Dim categories As CategoryCollection
categories = wiStore.Projects(project.Name).Categories
Dim wiType As String
wiType = categories("Requirement Category").DefaultWorkItemType.Name
' Query for the trees of active user stories in the team project collection
Dim queryString As 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 [Target].[System.State] = 'Active') ORDER BY [System.Id] mode(Recursive)")
Dim wiQuery As New Query(wiStore, queryString.ToString())
Dim wiTrees() As WorkItemLinkInfo
wiTrees = wiQuery.RunLinkQuery()
' Print the trees of user stories with the estimated size of each leaf.
PrintTrees(wiStore, wiTrees, " ", 0, 0)
Next
Next
Catch ex As Exception
Console.WriteLine(ex.Message)
End Try
End Sub