带有c#表达式的XAMLX Workflow

时间:2012-12-06 21:51:58

标签: c# workflow-foundation-4 workflow-foundation

我正在开发vs2012 / .Net 4.5 / WF 4.5中的自主工作流程,并且很难搞清楚以下消息

  

表达式活动类型'CSharpValue`1'需要编译才能运行。请确保已编译工作流程。

当我调用服务引用生成的活动时会发生此错误(当您添加WCF服务引用时,端点上的每个操作都会成为活动)。

在MSDN中查看我发现了这些文章:

他们说

  

当工作流服务托管在IIS或WAS中时,则不需要执行其他步骤,但如果XAML工作流服务是自托管的,则必须编译C#表达式

所以,我终于得到了我的问题:我应该怎么做才能点击F5并调试我的工作流程,让它在IIS上运行?并停止这个该死的例外...

我已尝试转到项目配置并设置为使用本地IIS,如下所示:iis config

但是因为我仍然得到错误,我认为它不起作用......

2 个答案:

答案 0 :(得分:4)

老问题,但经过一天拼凑各种信息之后,我想我会分享以防其他人遇到此问题。

来自C#表达式MSDN文档:

XAMLX工作流服务支持C#表达式。 在IIS或WAS中托管工作流服务时,不需要执行其他步骤,但如果XAML工作流服务是自托管的,则必须编译C#表达式。

在添加自定义WorkflowHostFactory之前,这是正确的。在这种情况下,如果重写错误的方法,则不会编译C#。以下代码不编译C#表达式,你会得到可怕的:

  

表达活动类型' CSharpValue`1'需要编译才能运行。请确保已编译工作流程。

或者,如果您不查看跟踪消息,则更有帮助:

  

System.ServiceModel.FaultException:无法执行操作,因为WorkflowInstance' 5cfc33d1-b546-4ba8-a8ec-86d3cb16a68b'被中止了。

   public override ServiceHostBase CreateServiceHost(string constructorString, Uri[] baseAddresses)
    {
        return base.CreateServiceHost(constructorString, baseAddresses);
    }

您可以通过覆盖其他工厂方法,然后使用MSDN C# Expressions in Workflow Foundation 4.5提供的代码编译您的活动来解决此问题:

 protected override WorkflowServiceHost CreateWorkflowServiceHost(WorkflowService service, Uri[] baseAddresses)
    {
        CompileExpressions(service.Body);
        return base.CreateWorkflowServiceHost(service, baseAddresses);
    }

以下是整个WorkflowServiceHostFactory:

 public class MyWorkflowServiceHostFactory : WorkflowServiceHostFactory
{
    protected override WorkflowServiceHost CreateWorkflowServiceHost(WorkflowService service, Uri[] baseAddresses)
    {
        CompileExpressions(service.Body);
        return base.CreateWorkflowServiceHost(service, baseAddresses);
    }

    static void CompileExpressions(Activity activity)
    {
        // activityName is the Namespace.Type of the activity that contains the
        // C# expressions.
        string activityName = activity.GetType().ToString();

        // Split activityName into Namespace and Type.Append _CompiledExpressionRoot to the type name
        // to represent the new type that represents the compiled expressions.
        // Take everything after the last . for the type name.
        string activityType = activityName.Split('.').Last() + "_CompiledExpressionRoot";
        // Take everything before the last . for the namespace.
        string activityNamespace = string.Join(".", activityName.Split('.').Reverse().Skip(1).Reverse());

        // Create a TextExpressionCompilerSettings.
        TextExpressionCompilerSettings settings = new TextExpressionCompilerSettings
        {
            Activity = activity,
            Language = "C#",
            ActivityName = activityType,
            ActivityNamespace = activityNamespace,
            RootNamespace = null,
            GenerateAsPartialClass = false,
            AlwaysGenerateSource = true,
            ForImplementation = false
        };

        // Compile the C# expression.
        TextExpressionCompilerResults results =
            new TextExpressionCompiler(settings).Compile();

        // Any compilation errors are contained in the CompilerMessages.
        if (results.HasErrors)
        {
            throw new Exception("Compilation failed.");
        }

        // Create an instance of the new compiled expression type.
        ICompiledExpressionRoot compiledExpressionRoot =
            Activator.CreateInstance(results.ResultType,
                new object[] { activity }) as ICompiledExpressionRoot;

        // Attach it to the activity.
        CompiledExpressionInvoker.SetCompiledExpressionRoot(
            activity, compiledExpressionRoot);
    }       
} 

答案 1 :(得分:-3)

尽管文章中提到了关于在IIS / WAS上运行的内容,但我只是设法运行了工作流程,当我实施结构化的时候......这不是问题的答案......它更像是一种解决方法... < / p>