2011-03-01 95 views
8

我希望TFS 2010在發生特定工作流程轉換時運行一些自定義代碼。那可能嗎?TFS在工作項目轉換時執行自定義代碼

我發現文檔有關自定義操作,這似乎是可以自動觸發工作項轉變(我會收到這樣嗎?)的行動我也發現了自定義活動,這些都與構建。但沒有任何符合這個特殊要求的東西 - 我錯過了什麼?

感謝您的幫助!

回答

14

這是非常可行的。

這是可行的,有很多方法可以做到這一點。我的最愛之一是製作服務器端插件。 (請注意,這僅適用於2010年TFS)

這些博客文章顯示的基本知識:

下面是一些代碼,我從開源修改項目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

要注意的一件重要的事情是,這個事件是一個通知(而不是一個決定點)。這意味着你沒有辦法阻止它。你只能對它做出反應。 – Vaccano 2011-03-02 00:08:07

+0

這正是我正在尋找的。非常感謝。 – 2011-03-02 14:05:17

+0

@Vaccano - 您的[TFS聚合器](http://tfsaggregator.codeplex.com/)項目對我們的團隊非常有用。只是想表示感謝......我現在正在使用Codeplex的項目來傳播最新的成果! – 2013-02-12 11:56:33

0

這裏是我的單例模式的一個例子

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

這裏是它是如何被引用的。

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