Wednesday, June 20, 2007

Compiling a XOML workflow

In my last post I talked about validating a XOML workflow. Another way to validate a workflow is to just try and compile it and see what you get back from the compiler. The disadvantage of this approach is the fact you have to start to write things out to file. So I've been validating using the previous method and then just compiling when necessary*. The downside of this approach is the x:Class attribute which can't be present when trying to execute a XOML workflow and must be present when trying to compile it. The simple workaround for this is to add the x:Class attribute before writing the XOML out to a temporary file. Anyway here's the code -

        // copy to a temporary file and add the x:Class attribute
        string tempFileName = Path.GetTempPath() + "temp.xoml";
        XmlDocument doc = new XmlDocument();
        doc.LoadXml(xoml);
        doc.DocumentElement.SetAttribute("Class", "http://schemas.microsoft.com/winfx/2006/xaml", WorkflowName);
        doc.Save(tempFileName);
        try
        {
          // Compile the workflow
          WorkflowCompiler compiler = new WorkflowCompiler();
          WorkflowCompilerParameters parameters = new WorkflowCompilerParameters();
          parameters.LibraryPaths.Add(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location));
          parameters.ReferencedAssemblies.Add("MyActivities.dll");
          parameters.OutputAssembly = string.Format("{0}.dll", WorkflowName);
          compilerResults = compiler.Compile(parameters, tempFileName);
        }
        finally
        {
          File.Delete(tempFileName);
        }
        
        StringBuilder errors = new StringBuilder();
        foreach (CompilerError compilerError in compilerResults.Errors)
        {
          errors.Append(compilerError.ToString() + '\n');
        }

        if (errors.Length != 0)
        {
          MessageBox.Show(this, errors.ToString(), this.Text, MessageBoxButtons.OK, MessageBoxIcon.Error);
          compileOK = false;
        }

* Another reason I did it this way was because I implemented the validation piece before I implemented the compilation piece and didn't realise I could just re-use the compiling code...

1 comment:

Anderson Imes said...

Very helpful. Thank you.