TFS在工作项转换上执行自定义代码

Jam*_*Orr 8 tfs workitem tfs2010

我希望TFS 2010在特定的工作流转换发生时运行一些自定义代码.那可能吗?

我找到了有关自定义操作的文档,这些操作似乎是可以自动触发工作项转换的操作(我是否正确?)我还找到了与Builds相关的自定义活动.但没有任何东西符合这一特殊要求 - 我错过了什么吗?

谢谢你的帮助!

Vac*_*ano 14

这是非常可行的.

它是如此可行,有很多方法可以做到这一点.我最喜欢的一个是制作服务器端插件.(注意,这仅适用于TFS 2010)

这些博客文章展示了基础知识:

这是我从我的开源项目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);
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 需要注意的一件重要事情是,此事件是一个通知(不是决策点).这意味着你无法阻止它.你只能对它做出反应. (2认同)