Question

I'm trying to use a composite custom activity that apply a regular expression and return a boolean if it match. The pattern is something encoded in design time. The source text is coming from an activity. This activity is also specified in design time (I've made a activity designer that allow to drop an activity as source)

But I also need to return what sub string match the expression, so I added an OutArgument to retrieve the string that match, and the string captured.

Here is the code:

public class RegularExpression : NativeActivity<bool>
{
    [RequiredArgument]
    public string Pattern { get; set; }

    public OutArgument<string> Captured { get; set; }

    [RequiredArgument]
    public Activity<string> RetrieveTextActivity { get; set; }

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

    protected override void Execute(NativeActivityContext context)
    {
        if (this.RetrieveTextActivity != null)
            context.ScheduleActivity<string>(this.RetrieveTextActivity, this.onRetrieveComplete);
    }

    private void onRetrieveComplete(NativeActivityContext context, ActivityInstance completedInstance, string result)
    {
        var regexp = new Regex(this.Pattern);
        var match = regexp.Match(result);

        this.Result.Set(context, match.Success);
        if (this.Captured != null)
            this.Captured.Set(context, match.Value);
    }
}

If I execute this activity without binding a variable to the Captured argument, it works as expected (the Result is correctly set).
But if I use the designer to add a variable, then I bind the variable to the Captured argument this error popup:

The argument of type 'System.String' cannot be used. Make sure that it is declared on an activity.

The exception is thrown when executing this line:

this.Captured.Set(context, match.Value);

Does someone have an idea why I can't set the argument ?
I also read that I shouldn't test that Captured is null, the runtime should automatically set a default value. But If I don't test, I've a NullReference when I don't bind a variable to the argument...

EDIT:
I want to add more information about the workflow itself. I've read in another topic that it may be VS. Here I just want to specify that I'm using a rehosted designer to create the workflow (and not VS). The workflow is then saved as XML in a database.
When I need to start a new workflow, I read the database, use XamlService.Load and Run the created workflow.

Was it helpful?

Solution

Does the error go away if you declare the argument in CacheMetadata?

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

    RuntimeArgument argument = new RuntimeArgument("Captured", typeof(string), ArgumentDirection.Out);
    metadata.Bind(this.Captured, argument);
    metadata.AddArgument(argument);

}

EDIT: I was too quick. The above code should now compile and hopefully fix your problem.

OTHER TIPS

My problem went away when I just called the base.CachMetadata(metadata) after my adds. Try:

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

You want to do it after your adds, because you want the base class to know what you've added when you call it. I think the base class uses reflection to do Damir Arh's answer for you automatically. This way you don't have to add or modify all that code every time you add or modify your properties. If you had a lot of properties it would become a pain real fast.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top