How to correctly load a WF4 workflow from XAML?

Viewed 12280

Short version:

How do I load a WF4 workflow from XAML? Important detail: The code that loads the workflow shouldn't need to know beforehand which types are used in the workflow.


Long version:

I am having a very hard time loading a WF4 workflow from the XAML file create by Visual Studio. My scenario is that I want to put this file into the database to be able to modify it centrally without recompiling the Workflow invoker.

I am currently using this code:

var xamlSchemaContext = new XamlSchemaContext(GetWFAssemblies());
var xmlReaderSettings = new XamlXmlReaderSettings();
xmlReaderSettings.LocalAssembly = typeof(WaitForAnySoundActivity).Assembly;
var xamlReader = ActivityXamlServices.CreateBuilderReader(
                     new XamlXmlReader(stream, xmlReaderSettings), 
                     xamlSchemaContext);

var activityBuilder = (ActivityBuilder)XamlServices.Load(xamlReader);
var activity = activityBuilder.Implementation;
var validationResult = ActivityValidationServices.Validate(activity);

This gives me a whole lot of errors, which fall into two categories:

Category 1:
Types from my assemblies are not known, although I provided the correct assemblies to the constructor of XamlSchemaContext.

ValidationError { Message = Compiler error(s) encountered processing expression "GreetingActivationResult.WrongPin". 'GreetingActivationResult' is not declared. It may be inaccessible due to its protection level. , Source = 10: VisualBasicValue, PropertyName = , IsWarning = False }

This can be solved by using the technique described here, which basically adds the assemblies and namespaces of all used types to some VisualBasicSettings instance:

var settings = new VisualBasicSettings();
settings.ImportReferences.Add(new VisualBasicImportReference
{
    Assembly = typeof(GreetingActivationResult).Assembly.GetName().Name,
    Import = typeof(GreetingActivationResult).Namespace
}); 
// ...
VisualBasic.SetSettings(activity, settings);
// ... Validate here

This works but makes the whole "dynamic loading" part of the Workflow a joke, as the code still needs to know all used namespaces.
Question 1: Is there another way to get rid of these validation errors without the need to know beforehand which namespaces and assemblies are used?

Category 2:
All my input arguments are unknown. I can see them just fine in activityBuilder.Properties but I still get validation errors saying they are unknown:

ValidationError { Message = Compiler error(s) encountered processing expression "Pin". 'Pin' is not declared. It may be inaccessible due to its protection level. , Source = 61: VisualBasicValue, PropertyName = , IsWarning = False }

No solution so far.
Question 2: How to tell WF4 to use the arguments defined in the XAML file?

4 Answers
Related