Создание своего Activity для WorkFlow

Возникла необходимость написания рабочего процесса утверждения/согласования документа в силу того, что стандартное не подходит (да и то, что в SharePoint Designer тоже не подошло). Работа, в сущности, происходит с Activity CreateTask и другими Activity, который связаны с ним: onTaskCreated, onTaskChanged и прочие. Сама работа с элементами в целом не сложна, если знать тонкости, конечно. Решил все эти события и Activity связанные с заданием запихнуть в один класс. Покажу как это выглядит примерно.

Создаём свой класс:

[Serializable]
public class ApprovalTask : SequenceActivity
{
        private string _prefix = "_ap_task";
        private string _path_prefix = string.Empty;
        private SPWorkflowActivationProperties _WorkflowProperties;   // параметры р.б.
        public Microsoft.SharePoint.WorkflowActions. CreateTaskWithContentType _Task;       // задание

        public SPWorkflowTaskProperties _TaskProperties;    // параметры задания
        private System.Workflow.ComponentModel.ActivityBind _activityCreateTask;
...
}
Наследуем его от SequenceActivity, что позволяет добавлять в него другие Activity. Как пример, рассмотрю Activity по созданию задания.

Добавляем конструктор:

public ApprovalTask(SPWorkflowActivationProperties workflowProperties, string AssignedTo, int Index)
{
    _WorkflowProperties = workflowProperties;
    _AssignedTo = AssignedTo;
    _Index = Index;
    _path_prefix = "Tasks[" + _Index.ToString() + "]";
    Initialize();
    AddActivities();
}
Для элементов рабочего процесса обязательно задавать корреляцию. Экземпляры своего класса храним в массиве созданном в рабочем процессе.
public List<ApprovalTask> Tasks = new List<ApprovalTask>();
Поэтому _path_prefix так и выглядит. Эта переменная используется для настройки корреляции.

AddActivities добавляет созданные Activity в список Activity нашего класса:

public void AddActivities()
{
    this.Activities.Add(this._Task);
}

Initialize() производит начальную инициализацию элементов:

public void Initialize()
{
    _Task = new CreateTaskWithContentType();
    _TaskProperties = new Microsoft.SharePoint.Workflow. SPWorkflowTaskProperties();

    _Token = new System.Workflow.Runtime.CorrelationToken();
    _Token.Name = _prefix + "_TaskToken2";
    _Token.OwnerActivityName = "Workflow1";
    _Task.CorrelationToken = _Token;
    _Task.Name = _prefix + "_Task2";
    _Task.TaskId = Guid.NewGuid();

    _activityCreateTask.Name = "Workflow1";
    _activityCreateTask.Path = _path_prefix + "._TaskProperties";
    _Task.SetBinding(Microsoft.SharePoint.WorkflowActions. CreateTaskWithContentType.TaskPropertiesProperty, ((System.Workflow.ComponentModel.ActivityBind) (_activityCreateTask)));
    _Task.TaskProperties = _TaskProperties;
    _Task.MethodInvoking += new System.EventHandler(ApprovalTask_MethodInvoking);
}
_activityCreateTask используется для настройки корреляции. У него необходимо задать два свойства: имя владельца (в нашем случае рабочий процесс с именем Workflow1) и путь до переменной.

Собственно всё. Теперь необходимо в рабочем процессе добавить Activity в WorkFlow во время выполнения. Что-то вроде:

Tasks.Add(new ApprovalTask(workflowProperties, _AssignedTo, Tasks.Count));
WorkflowChanges changes = new WorkflowChanges(this);
((SequenceActivity)changes.TransientWorkflow. GetActivityByName("sequenceActivity1")). Activities.Add(Tasks[0]);
this.ApplyWorkflowChanges(changes);