2

Scenario: I'm implementing a parent activity which executes other activity from external source(database), following this Ron Jacobs post.

This approach works but have a few problems in my case, because WorkflowInvoker don't get the parent extensions:

  • Tracking is disabled for childrens
  • My custom data sharing extension don't work
  • Extensions can change depending on the host, so I can't simply add new ones again.

Potential solution: Instead of Invoke the children XAML, I'm scheduling it(I believe it will solve my problems, right?).

CacheMetadata: load the DynamicActivity from the external source and call metadata.AddChild(_childActivity);.

Then execute:

    protected override void Execute(NativeActivityContext context)
    {
        context.ScheduleActivity(_childActivity, OnActivityComplete);
    }

And it worked! Next step would be pass In, Out and InOut arguments to children.

Problem: How to Schedule children DynamicActivity loaded from external XAML with InArgument, OutArgument and InOutArgument values

Something I'm doing but is working just for OutArguments. In CacheMetadata I called my method _childActivity.BindArguments

    public static void BindArguments(this DynamicActivity activity, IDictionary<string, Argument> argumentsToBind)
    {
        if (argumentsToBind == null)
            return;

        Type genericPropType, valueType, sourceArgumentType, vbReferenceType;
        Argument sourceArgument;
        foreach (var destinyArgument in activity.Properties)
        {
            if (!argumentsToBind.TryGetValue(destinyArgument.Name, out sourceArgument))
                continue;

            genericPropType = destinyArgument.Type.GetGenericTypeDefinition();
            if (genericPropType == typeof(InArgument<>))
            {
                destinyArgument.Value = new InArgument<string>("It worked! But I need the value from context which is unavaliable since I'm inside CacheMetadata");
            }
            else
            {
                valueType = destinyArgument.Type.GetGenericArguments()[0];
                sourceArgumentType = genericPropType.MakeGenericType(valueType);

                if (sourceArgument != null)
                {
                    vbReferenceType = typeof(VisualBasicReference<>).MakeGenericType(valueType);

                    object vbReference = Activator.CreateInstance(vbReferenceType,
                        GetExpressionText(sourceArgument, sourceArgumentType));

                    object referenceArgument = Activator.CreateInstance(sourceArgumentType, vbReference);

                    destinyArgument.Value = referenceArgument;
                }
            }
        }
    }

So, I need to pass InArguments and InOutArguments too but I need the value from context which is unavaliable since I'm inside CacheMetadata.

I tried to set the DynamicActivityProperty.Value in the Execute method. But it doesn't worked too.

After, I founded this page that may help you to understand my scenario.

Davi Fiamenghi
  • 1,237
  • 12
  • 28

1 Answers1

3

Instead of doing all of this have you considered passing messages to the child workflow? Workflows hosting other workflows is not an area that is well supported (as you have discovered). Instead Workflows sending messages to other workflows seems to be a better approach. Of course, you can't share tracking and extensions. I did come up with a way to support tracking in the child workflow but it uses private reflection.

Ron Jacobs
  • 3,279
  • 2
  • 18
  • 16
  • My critical point was a data sharing extension which had a companyId for infrastructure purposes and I needed this id. I ended up re-passing the extension instance. Anyways, as you surely know how to properly instantiate In/InOutArgument in this case, I think it's totally possible to do and think that would be great for WF4 and community to have an extension sharing capable version of the LoadAndInvokeWorkflow(mainly because tracking and persistence) and schedule the child in LoadAndInvokeWorkflow would look more natural, well just my point of view. Thank you very much for helping – Davi Fiamenghi Mar 01 '12 at 04:51
  • I wanted to support extension sharing but unfortunately there is no way to enumerate extensions in a given workflow host. Under the covers it isn't a simple collection either. I suppose I could alter the API to allow you to pass values... might be a good idea. – Ron Jacobs Mar 02 '12 at 16:28
  • I understand what you wanted to do. Iterate over parent extensions and add then to children, right? My idea was a little different. Do you think that scheduling(and caching metadata) of the children XAML activity will turn it in a well known children and be executed in the same context, allowing extension 'sharing'? – Davi Fiamenghi Mar 02 '12 at 18:43
  • 2
    I'm updating Microsoft.Activities.Extensions to allow you to pass a collection of extensions to the child workflow. This will allow you to pass your data sharing extension to the child workflow. Will be in the next release. – Ron Jacobs Mar 07 '12 at 21:59
  • That is GREAT!!! Will it support tracking too? I will surely examine the code to see how you did it!! ;D – Davi Fiamenghi Mar 08 '12 at 15:34
  • Are you planning to consider *TrackingProfile.ImplementationVisibility[All, RootScope]* in the new *LoadAndInvokeWorkflow*? Thanks – Davi Fiamenghi Aug 02 '12 at 15:29