How to call an Activity inside another Activity in

2020-03-31 08:03发布

问题:

I have created a Native activity and I need to call another activity on a Bookmark Resume call. My First Activity name is "Apply" and Second activity is called "Approve". In Apply, i have created a property as below.

  public Approve Approve
    {
        get;
        set;
    }

and then I have registered the CacheMetadata as below.

        metadata.AddImplementationChild(this.Approve);
        base.CacheMetadata(metadata);

And then "OnResumeBookmark" method, Im scheduling it.

        this.Approve = new Approve();
        this.Approve.ID = context.GetValue(this.ID);
        OutArgument<string> res = this.Approve.Result;
        context.ScheduleActivity(this.Approve);

But When it runs, it gives me the below error.

The provided activity was not part of this workflow definition when its metadata was being processed. The problematic activity named 'Approve' was provided by the activity named 'Apply'.

Could you please help me to resolve this?

回答1:

There are two approaches to activity development:

  • The Private Implementation Route
  • The Public Implementation Route

It appears you are working on the private implementation strategy from your question, but I'll provide sample code for both ways below.

The Private Implementation Way

In this approach, the Apply activity is responsible for setting up everything about the Approve child activity. We wire up the ID property using the WF Variable<string> object. Also, we inform the WF run time that the Approve activity can be scheduled by the Apply activity, just like you have in your code sample.

public class Approve : CodeActivity
{
    public InArgument<string> Something
    {
        get; set;
    }

    protected override void Execute(CodeActivityContext context)
    {
        var message = string.Format("Approval of {0} in process... please wait.", this.Something.Get(context));
        Console.WriteLine(message);
    }
}

public class Apply : NativeActivity
{
    private readonly Approve approve;
    private readonly Variable<string> thingToApproveVar;

    public Apply()
    {
        this.thingToApproveVar = new Variable<string>();
        this.approve = new Approve();
        this.approve.Something = new InArgument<string>(this.thingToApproveVar);
    }

    protected override void CacheMetadata(NativeActivityMetadata metadata)
    {
        metadata.AddImplementationVariable(this.thingToApproveVar);
        metadata.AddImplementationChild(this.approve);
    }

    protected override void Execute(NativeActivityContext context)
    {
        Console.WriteLine("Approving...");
        this.thingToApproveVar.Set(context, "Hello");
        context.ScheduleActivity(this.approve, this.OnApprovalCompleted);
    }

    private void OnApprovalCompleted(NativeActivityContext activityContext, ActivityInstance instance)
    {
        Console.WriteLine("Apply succeeded!");
    }
}

The Public Implementation Way

The second approach in developing your activity is to define your Apply activity to simply schedule the Approve activity. The CacheMetadata method needs a slight tweak for this though, by using the AddChild method instead of the AddImplementationChild method.

public class Apply : NativeActivity
{
    public Apply()
    {
    }

    public Approve Approve { get; set; }

    protected override void CacheMetadata(NativeActivityMetadata metadata)
    {
        metadata.AddChild(this.Approve);
    }

    protected override void Execute(NativeActivityContext context)
    {
        context.ScheduleActivity(this.Approve, this.OnApprovalCompleted);
    }

    private void OnApprovalCompleted(NativeActivityContext activityContext, ActivityInstance instance)
    {
        Console.WriteLine("Apply succeeded!");
    }
}

And to execute the "public implementation way", it would look like the following:

class Program
{
    static void Main(string[] args)
    {
        WorkflowInvoker.Invoke(new Sequence()
        {
            Activities =
            {
                new Apply()
                {
                    Approve = new Approve()
                    {
                        Something = "Hello World!"
                    }
                }
            }
        });
    }
}