Scheduling a set lead time in a 4 RC workflow

therefore, I have this requirement to begin work provided to me at runtime. To facilitate this, I created a WorkflowService that takes actions like Xaml, moisturizes them and repels them.

That sounds easy enough ...

... this is my Xaml WorkflowService

<Activity 
    x:Class="Workflow.Services.WorkflowService.WorkflowService" 
    ...
    xmlns:local1="clr-namespace:Workflow.Activities" >
  <Sequence sap:VirtualizedContainerService.HintSize="277,272">
    <Sequence.Variables>
      <Variable x:TypeArguments="local:Workflow" Name="Workflow" />
    </Sequence.Variables>
    <sap:WorkflowViewStateService.ViewState>
      <scg3:Dictionary x:TypeArguments="x:String, x:Object">
        <x:Boolean x:Key="IsExpanded">True</x:Boolean>
      </scg3:Dictionary>
    </sap:WorkflowViewStateService.ViewState>
    <p:Receive CanCreateInstance="True" DisplayName="ReceiveSubmitWorkflow" sap:VirtualizedContainerService.HintSize="255,86" OperationName="SubmitWorkflow" ServiceContractName="IWorkflowService">
      <p:ReceiveParametersContent>
        <OutArgument x:TypeArguments="local:Workflow" x:Key="workflow">[Workflow]</OutArgument>
      </p:ReceiveParametersContent>
    </p:Receive>
    <local1:InvokeActivity Activity="[ActivityXamlServices.Load(New System.IO.StringReader(Workflow.Xaml))]" sap:VirtualizedContainerService.HintSize="255,22" />
  </Sequence>
</Activity>

... which, with the exception of reusing "Workflow", is pretty straight forward. In fact, it's just Sequencewith Receiveand [currently] customizable activity called InvokeActivity. Come to this a bit.

Receive The action takes a custom type,

[DataContract]
public class Workflow
{
    [DataMember]
    public string Xaml { get; set; }
}

which contains a string whose contents should be interpreted as Xaml. You can see the VB expression, which then converts this Xaml to Activity and passes it.

, InvokeActivity, .

:

1), , [ ], , WF4RC, ? , API , :)

-:

2) InvokeActivity :

public sealed class InvokeActivity : NativeActivity
{
    private static readonly ILog _log = 
        LogManager.GetLogger (typeof (InvokeActivity));

    public InArgument<Activity> Activity { get; set; }

    public InvokeActivity ()
    {
        _log.DebugFormat ("Instantiated.");
    }

    protected override void Execute (NativeActivityContext context)
    {
        Activity activity = Activity.Get (context);

        _log.DebugFormat ("Scheduling activity [{0}]...", activity.DisplayName);

        // throws exception to lack of metadata! :(
        ActivityInstance instance = 
            context.ScheduleActivity (activity, OnComplete, OnFault);

        _log.DebugFormat (
            "Scheduled activity [{0}] with instance id [{1}].", 
            activity.DisplayName, 
            instance.Id);
    }

    protected override void CacheMetadata (NativeActivityMetadata metadata)
    {
        // how does one add InArgument<T> to metadata? not easily
        // is my first guess
        base.CacheMetadata (metadata);
    }

    // private methods

    private void OnComplete (
        NativeActivityContext context, 
        ActivityInstance instance)
    {
        _log.DebugFormat (
            "Scheduled activity [{0}] with instance id [{1}] has [{2}].",
            instance.Activity.DisplayName, 
            instance.Id, 
            instance.State);
    }

    private void OnFault (
        NativeActivityFaultContext context, 
        Exception exception, 
        ActivityInstance instance)
    {
        _log.ErrorFormat (
@"Scheduled activity [{0}] with instance id [{1}] has faulted in state [{2}] 
{3}", 
            instance.Activity.DisplayName, 
            instance.Id, 
            instance.State, 
            exception.ToStringFullStackTrace ());
    }
}

. , . , .

, . " " ​​ "InvokeActivity".

, "" , , InvokeActivity. Googled this. , InArgument<Activity> , , , , ? context.ScheduleActivity (...) ?

,

3) [ ] ,

public sealed class InvokeActivity : NativeActivity
{
    private static readonly ILog _log = 
        LogManager.GetLogger (typeof (InvokeActivity));

    public InArgument<Activity> Activity { get; set; }

    public InvokeActivity ()
    {
        _log.DebugFormat ("Instantiated.");
    }

    protected override void Execute (NativeActivityContext context)
    {
        Activity activity = Activity.Get (context);

        _log.DebugFormat ("Invoking activity [{0}] ...", activity.DisplayName);

        // synchronous execution ... a little less than ideal, this
        // seems heavy handed, and not entirely semantic-equivalent
        // to what i want. i really want to invoke this runtime
        // activity as if it were one of my own, not a separate
        // process - wrong mentality?
        WorkflowInvoker.Invoke (activity);

        _log.DebugFormat ("Invoked activity [{0}].", activity.DisplayName);
    }

}

[ WF4-, , ]. , WF- , , . , : , (.. ), ?

, :)

+3
1

, . DynamicActivity ​​ > named 'InvokeActivity'.

Workflow 4.0 , .

, , , worklfow. A , B , .

, , , - (, , ).

+2

Source: https://habr.com/ru/post/1735315/


All Articles