老问题,但是在拼凑了一天的各种信息之后,我想我会分享一下,以防其他人遇到这个问题。
从 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);
}
您可以通过覆盖其他工厂方法,然后使用通过Workflow Foundation 4.5 中的 MSDN C# Expressions提供的代码编译您的活动来解决此问题:
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);
}
}