2011-03-01 10 views
8

Me gustaría que TFS 2010 ejecute un código personalizado cada vez que se produce una transición de flujo de trabajo particular. ¿Es eso posible?TFS Ejecutar código personalizado en una transición de elemento de trabajo

He encontrado documentación sobre acciones personalizadas, que parecen ser acciones que pueden activar automáticamente transiciones de elementos de trabajo (¿me sale bien?) También encontré actividades personalizadas, que están relacionadas con Builds. Pero nada que sirva para este requisito en particular: ¿me estoy perdiendo algo?

Gracias por su ayuda!

Respuesta

14

Esto es muy factible.

Es tan factible, que hay muchas maneras de hacerlo. Uno de mis favoritos es hacer un complemento del lado del servidor. (Nota: esto sólo funciona en TFS 2010)

Estas entradas de blog muestran los conceptos básicos:

Aquí hay un código que he modificado de mi código abierto proyecto TFS Aggregator:

public class WorkItemChangedEventHandler : ISubscriber 
{  
    /// <summary> 
    /// This is the one where all the magic starts. Main() so to speak. 
    /// </summary> 
    public EventNotificationStatus ProcessEvent(TeamFoundationRequestContext requestContext, NotificationType notificationType, object notificationEventArgs, 
               out int statusCode, out string statusMessage, out ExceptionPropertyCollection properties) 
    { 
     statusCode = 0; 
     properties = null; 
     statusMessage = String.Empty; 
     try 
     { 
      if (notificationType == NotificationType.Notification && notificationEventArgs is WorkItemChangedEvent) 
      { 
       // Change this object to be a type we can easily get into 
       WorkItemChangedEvent ev = notificationEventArgs as WorkItemChangedEvent; 
       // Connect to the setting file and load the location of the TFS server 
       string tfsUri = TFSAggregatorSettings.TFSUri; 
       // Connect to TFS so we are ready to get and send data. 
       Store store = new Store(tfsUri); 
       // Get the id of the work item that was just changed by the user. 
       int workItemId = ev.CoreFields.IntegerFields[0].NewValue; 
       // Download the work item so we can update it (if needed) 
       WorkItem eventWorkItem = store.Access.GetWorkItem(workItemId); 

       if ((string)(eventWorkItem.Fields["State"].Value) == "Done") 
        { 
         // If the estimated work was changed then revert it back. 
         // We are in done and don't want to allow changes like that. 
         foreach (IntegerField integerField in ev.ChangedFields.IntegerFields) 
         { 
          if (integerField.Name == "Estimated Work") 
          { 
           eventWorkItem.Open(); 
           eventWorkItem.Fields["Estimated Work"].Value = integerField.OldValue; 
           eventWorkItem.Save(); 
          } 
         } 
        } 
       } 
      } 

     } 
     return EventNotificationStatus.ActionPermitted; 
    } 

    public string Name 
    { 
     get { return "SomeName"; } 
    } 

    public SubscriberPriority Priority 
    { 
     get { return SubscriberPriority.Normal; } 
    } 

    public WorkItemChangedEventHandler() 
    { 
     //DON"T ADD ANYTHING HERE UNLESS YOU REALLY KNOW WHAT YOU ARE DOING. 
     //TFS DOES NOT LIKE CONSTRUCTORS HERE AND SEEMS TO FREEZE WHEN YOU TRY :(
    } 

    public Type[] SubscribedTypes() 
    { 
     return new Type[1] { typeof(WorkItemChangedEvent) }; 
    } 
} 

/// <summary> 
/// Singleton Used to access TFS Data. This keeps us from connecting each and every time we get an update. 
/// </summary> 
public class Store 
{ 
    private readonly string _tfsServerUrl; 
    public Store(string tfsServerUrl) 
    { 
     _tfsServerUrl = tfsServerUrl; 
    } 

    private TFSAccess _access; 
    public TFSAccess Access 
    { 
     get { return _access ?? (_access = new TFSAccess(_tfsServerUrl)); } 
    } 
} 

/// <summary> 
/// Don't use this class directly. Use the StoreSingleton. 
/// </summary> 
public class TFSAccess 
{ 
    private readonly WorkItemStore _store; 
    public TFSAccess(string tfsUri) 
    { 
     TfsTeamProjectCollection tfs = new TfsTeamProjectCollection(new Uri(tfsUri)); 
     _store = (WorkItemStore)tfs.GetService(typeof(WorkItemStore)); 
    } 

    public WorkItem GetWorkItem(int workItemId) 
    { 
     return _store.GetWorkItem(workItemId); 
    } 
} 
+2

Una cosa importante a tener en cuenta es que este evento es una notificación (no un punto de decisión). Eso significa que no hay nada que puedas hacer para bloquearlo. Solo puedes reaccionar a eso. – Vaccano

+0

Esto es justo lo que estaba buscando. Muchas gracias. –

+0

@Vaccano - su proyecto [TFS Aggregator] (http://tfsaggregator.codeplex.com/) ha sido útil para nuestro equipo. Solo quería decir gracias ... ¡Me voy ahora a tu proyecto en codeplex para difundir los votos favorables! –

0

Aquí hay un ejemplo de mi patrón singleton

public class TFSSingleton 
{ 
    private static TFSSingleton _tFSSingletonInstance; 
    private TfsTeamProjectCollection _teamProjectCollection; 
    private WorkItemStore _store; 

    public static TFSSingleton Instance 
    { 
     get 
     { 
      if (_tFSSingletonInstance == null) 
      { 
       _tFSSingletonInstance = new TFSSingleton(); 
      } 
      return _tFSSingletonInstance; 
     } 
    } 

    public TfsTeamProjectCollection TeamProjectCollection 
    { 
     get { return _teamProjectCollection; } 
    } 

    public WorkItemStore RefreshedStore 
    { 
     get 
     { 
      _store.RefreshCache(); 
      return _store; 
     } 
    } 

    public WorkItemStore Store 
    { 
     get { return _store; } 
    } 

    private TFSSingleton() 
    { 
     NetworkCredential networkCredential = new NetworkCredential("pivotalautomation", "*********", "***********"); 


     // Instantiate a reference to the TFS Project Collection 
     _teamProjectCollection = new TfsTeamProjectCollection(new Uri("http://********:8080/tfs/**********"), networkCredential); 
     _store = (WorkItemStore)_teamProjectCollection.GetService(typeof(WorkItemStore)); 
    } 
} 

y aquí se explica cómo se hace referencia a él.

WorkItemTypeCollection workItemTypes = TFSSingleton.Instance.Store.Projects[projectName].WorkItemTypes; 
Cuestiones relacionadas