2009-11-21 5 views
2

Я пытаюсь реализовать действие, подобное InvokeWorkflow, которое может динамически загружать файл XOML, создавать из него дерево действий и использовать его в качестве единственного его дочернего элемента.Динамическая загрузка рабочего процесса из XOML

Это будет похоже на InvokeWorkflow, за исключением того, что операции, которые динамически загружаются, встроены в основной рабочий процесс (что лучше с точки зрения мониторинга).

Я рассматривал XamlReader как потенциальный способ сделать это, но, по-видимому, он не подходит для загрузки рабочих процессов (только для пользовательского интерфейса).

Спасибо, Julien

ответ

1

Большое спасибо Энтони.

Я должен сказать, что ваша динамическая модификация рабочего процесса классная, но это было немного страшно. Я закончил составление рабочих процессов, используя модификацию Jon Flander's CallWorkflowActivity.

Некоторые приемы, которые я узнал с XOML только рабочие процессы загружаются во время выполнения (с использованием WF 3.5):

  • удалить х: атрибут класса внутри XOML

  • удалить файл кода

  • для конструктора VS для работы, эти файлы XOML необходимо разделить в своих проектах (в проекте, где находится XOML, нет кода, такого как базовые операции или общие типы)

  • отмечают XOML в содержании в VS и Copy Всегда так оно помещается в исполняемые файлы

  • даже так, VS 2008 обычно требуется полный Rebuild для того, чтобы правильно скопировать вновь модифицирована XOML файлы ...

  • вам может понадобиться установить контрольные точки вручную, как описано here

+0

ссылка не работает :( –

2

Достижение вашей цели здесь, вероятно, будет довольно сложно, однако позволяет начать с простой бит: -

Вы можете восстановить последовательность действий с XOML использованием WorkflowMarkupSerializer найденную в System.Workflow.ComponentModel.Serialization пространстве имен ,

var serializer = new WorkflowMarkupSerializer(); 
object root = serializer.Deserialize(myXmlReader); 

Аналогично можно реконструировать «фрагмент» деятельность, состоявшийся в то, что наследуется от CompositeActivity использования CompostiteActivityMarkupSerializer.

Однако для интеграции нового действия root в текущий рабочий процесс требуется больше работы. Для создания нового действия вам необходимо использовать экземпляр класса WorkflowChanges, изменив определение рабочего процесса, используемое текущим экземпляром.

Теперь документация - это какая-то отрывочная и даже немного уклончивая по этому вопросу. Два важных момента можно почерпнуть хотя: -

  1. В конечном итоге вызов ApplyWorkflowChanges нужен и этот элемент имеет protected доступность.
  2. Документация указывает, что это должно произойти в корневой активности рабочего процесса.

Следовательно, мы можем сделать вывод о том, что для выполнения этого требования нам понадобится пользовательская корневая активность.

Возможно, существует множество способов структурирования этого метода, но предположим, что у нас есть SequenceActivity, в котором у нас есть пользовательская активность «InvokeWorkflow», выполняющая модификацию рабочего процесса, и мы намерены поместить полученную новую активность в конец, содержащую последовательность ,

Сначала нужно определение интерфейса, который мы можем реализовать на заказ корневой деятельности: -

internal interface IModifiableWorkflow 
{ 
    void ApplyWorkflowChanges(WorkflowChanges workflowChanges); 
} 

В нашей пользовательской корневой активности мы бы реализовать этот интерфейс явно: -

public class CustomSequentialActivity : SequentialWorkflowActivity, IModifiableWorkflow 
{ 
    void IModifiableWorkflow.ApplyWorkflowChanges(WorkflowChanges workflowChanges) 
    { 
     base.ApplyWorkflowChanges(workflowChanges); 
    } 
} 

В способе пользовательского действия «InvokeWorkflow» Execute: -

// Get root activity  
var root = this.Parent; 
while (root.Parent != null) { root = root.Parent; } 

// Create an instance of WorkflowChanges based on the root activity 
var changes = new WorkflowChanges(root); 

//Find the parent sequence activity in the transient workflow definition 
var target = changes.TransientWorkflow.GetActivityByName(this.Parent.Name); 

Activity newActivity = YourCodeToLoadActivityDetailsFromXoml(); 

target.Activities.Add(newActivity); 

//Apply the new changes 
((IModifiableWorkflow)root).ApplyWorkflowChanges(changes); 

Примечание. Я на самом деле не протестировал ни одно из этого, его вымолотый кусок из крошек информации, похожей на документацию.