无法使用 WF 4.5 中的 CSharpValue 表达式访问字典
Unable to access Dictionary using CSharpValue expression in WF 4.5
我已尝试使用代码创建工作流,如 here 所述。但是我无法通过我的结果。我创建了控制台应用程序 Class1.cs 包含我的工作流代码和
Program.cs 工作流托管在 WorkflowApplication class 中,包括输入。在执行消息时发生未处理的异常
"Expression Activity type 'CSharpValue`1' requires compilation in order to run. Please ensure that the workflow has been compiled"。但我也有
包括用于编译的方法 CompileExpressions,如 here 所述。非常感谢您的帮助!
ReverseStringWorkflow.cs
public class ReverseStringWorkflow : Activity
{
public InArgument<Dictionary<string,object>> StringToReverse { get; set; }
protected override Func<Activity> Implementation
{
get
{
return () =>
{
Sequence sequence = new Sequence
{
Activities =
{
new WriteLine
{
Text = new CSharpValue<string>("StringToReverse[\"name\"].ToString()")
}
}
};
return sequence;
};
}
set
{
base.Implementation = value;
}
}
}
Program.cs
class Program
{
static void Main(string[] args)
{
Activity workflow2 = new ReverseStringWorkflow();
Dictionary<string, object> mainInputs = new Dictionary<string, object>();
Dictionary<string, object> subInputs = new Dictionary<string, object>();
subInputs.Add("name","name123");
mainInputs.Add("StringToReverse", subInputs);
WorkflowApplication app = new WorkflowApplication(workflow2, mainInputs);
app.OnUnhandledException = delegate (WorkflowApplicationUnhandledExceptionEventArgs e)
{
Console.WriteLine("Error occurred");
return UnhandledExceptionAction.Terminate;
};
CompileExpressions(workflow2);
app.Run();
Console.ReadLine();
}
public 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);
}
}
完整的错误信息:
[System.NotSupportedException] {System.NotSupportedException: Expression Activity type 'CSharpValue`1' requires compilation in order to run. Please ensure that the workflow has been compiled.
at System.Activities.Expressions.CompiledExpressionInvoker.InvokeExpression(ActivityContext activityContext)
at Microsoft.CSharp.Activities.CSharpValue`1.Execute(CodeActivityContext context)
at System.Activities.CodeActivity`1.InternalExecuteInResolutionContext(CodeActivityContext context)
at System.Activities.Runtime.ActivityExecutor.ExecuteInResolutionContext[T](ActivityInstance parentInstance, Activity`1 expressionActivity)
at System.Activities.InArgument`1.TryPopulateValue(LocationEnvironment targetEnvironment, ActivityInstance activityInstance, ActivityExecutor executor)
at System.Activities.RuntimeArgument.TryPopulateValue(LocationEnvironment targetEnvironment, ActivityInstance targetActivityInstance, ActivityExecutor executor, Object argumentValueOverride, Location resultLocation, Boolean skipFastPath)
at System.Activities.ActivityInstance.InternalTryPopulateArgumentValueOrScheduleExpression(RuntimeArgument argument, Int32 nextArgumentIndex, ActivityExecutor executor, IDictionary`2 argumentValueOverrides, Location resultLocation, Boolean isDynamicUpdate)
at System.Activities.ActivityInstance.ResolveArguments(ActivityExecutor executor, IDictionary`2 argumentValueOverrides, Location resultLocation, Int32 startIndex)
at System.Activities.Runtime.ActivityExecutor.ExecuteActivityWorkItem.ExecuteBody(ActivityExecutor executor, BookmarkManager bookmarkManager, Location resultLocation)
谢谢 Maciej Los 先生。最后我从你推荐的 the article 得到了正确的方法,你的回复很有帮助..
如果以后有人需要,这里是答案。
static void Main(string[] args)
{
Dictionary<string, object> inputs = new Dictionary<string, object>();
inputs.Add("userName", "Test User");
// Using DynamicActivity for this sample so that we can have an
// InArgument, and also do everything without XAML at all
DynamicActivity codeWorkflow = new DynamicActivity();
codeWorkflow.Name = "MyScenario.MyDynamicActivity";
foreach (var key in inputs.Keys)
{
DynamicActivityProperty property = new DynamicActivityProperty();
property.Name = key;
property.Type = typeof(InArgument<Dictionary<string,object>>);
codeWorkflow.Properties.Add(property);
}
codeWorkflow.Implementation = () => new WriteLine
{
Text = new CSharpValue<string>
{
ExpressionText = "\"hello ! \" + InArguments[\"userName\"].ToString()"
},
};
Compile(codeWorkflow);
WorkflowInvoker.Invoke(codeWorkflow,
new Dictionary<string, object>
{
{ "InArguments", inputs}
});
Console.ReadLine();
}
编译方法为:
static void Compile(DynamicActivity dynamicActivity)
{
TextExpressionCompilerSettings settings = new TextExpressionCompilerSettings
{
Activity = dynamicActivity,
Language = "C#",
ActivityName = dynamicActivity.Name.Split('.').Last() + "_CompiledExpressionRoot",
ActivityNamespace = string.Join(".", dynamicActivity.Name.Split('.').Reverse().Skip(1).Reverse()),
RootNamespace = null,
GenerateAsPartialClass = false,
AlwaysGenerateSource = true,
};
TextExpressionCompilerResults results =
new TextExpressionCompiler(settings).Compile();
if (results.HasErrors)
{
throw new Exception("Compilation failed.");
}
ICompiledExpressionRoot compiledExpressionRoot =
Activator.CreateInstance(results.ResultType,
new object[] { dynamicActivity }) as ICompiledExpressionRoot;
CompiledExpressionInvoker.SetCompiledExpressionRootForImplementation(
dynamicActivity, compiledExpressionRoot);
}
我已尝试使用代码创建工作流,如 here 所述。但是我无法通过我的结果。我创建了控制台应用程序 Class1.cs 包含我的工作流代码和 Program.cs 工作流托管在 WorkflowApplication class 中,包括输入。在执行消息时发生未处理的异常 "Expression Activity type 'CSharpValue`1' requires compilation in order to run. Please ensure that the workflow has been compiled"。但我也有 包括用于编译的方法 CompileExpressions,如 here 所述。非常感谢您的帮助!
ReverseStringWorkflow.cs
public class ReverseStringWorkflow : Activity
{
public InArgument<Dictionary<string,object>> StringToReverse { get; set; }
protected override Func<Activity> Implementation
{
get
{
return () =>
{
Sequence sequence = new Sequence
{
Activities =
{
new WriteLine
{
Text = new CSharpValue<string>("StringToReverse[\"name\"].ToString()")
}
}
};
return sequence;
};
}
set
{
base.Implementation = value;
}
}
}
Program.cs
class Program
{
static void Main(string[] args)
{
Activity workflow2 = new ReverseStringWorkflow();
Dictionary<string, object> mainInputs = new Dictionary<string, object>();
Dictionary<string, object> subInputs = new Dictionary<string, object>();
subInputs.Add("name","name123");
mainInputs.Add("StringToReverse", subInputs);
WorkflowApplication app = new WorkflowApplication(workflow2, mainInputs);
app.OnUnhandledException = delegate (WorkflowApplicationUnhandledExceptionEventArgs e)
{
Console.WriteLine("Error occurred");
return UnhandledExceptionAction.Terminate;
};
CompileExpressions(workflow2);
app.Run();
Console.ReadLine();
}
public 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);
}
}
完整的错误信息:
[System.NotSupportedException] {System.NotSupportedException: Expression Activity type 'CSharpValue`1' requires compilation in order to run. Please ensure that the workflow has been compiled.
at System.Activities.Expressions.CompiledExpressionInvoker.InvokeExpression(ActivityContext activityContext)
at Microsoft.CSharp.Activities.CSharpValue`1.Execute(CodeActivityContext context)
at System.Activities.CodeActivity`1.InternalExecuteInResolutionContext(CodeActivityContext context)
at System.Activities.Runtime.ActivityExecutor.ExecuteInResolutionContext[T](ActivityInstance parentInstance, Activity`1 expressionActivity)
at System.Activities.InArgument`1.TryPopulateValue(LocationEnvironment targetEnvironment, ActivityInstance activityInstance, ActivityExecutor executor)
at System.Activities.RuntimeArgument.TryPopulateValue(LocationEnvironment targetEnvironment, ActivityInstance targetActivityInstance, ActivityExecutor executor, Object argumentValueOverride, Location resultLocation, Boolean skipFastPath)
at System.Activities.ActivityInstance.InternalTryPopulateArgumentValueOrScheduleExpression(RuntimeArgument argument, Int32 nextArgumentIndex, ActivityExecutor executor, IDictionary`2 argumentValueOverrides, Location resultLocation, Boolean isDynamicUpdate)
at System.Activities.ActivityInstance.ResolveArguments(ActivityExecutor executor, IDictionary`2 argumentValueOverrides, Location resultLocation, Int32 startIndex)
at System.Activities.Runtime.ActivityExecutor.ExecuteActivityWorkItem.ExecuteBody(ActivityExecutor executor, BookmarkManager bookmarkManager, Location resultLocation)
谢谢 Maciej Los 先生。最后我从你推荐的 the article 得到了正确的方法,你的回复很有帮助..
如果以后有人需要,这里是答案。
static void Main(string[] args)
{
Dictionary<string, object> inputs = new Dictionary<string, object>();
inputs.Add("userName", "Test User");
// Using DynamicActivity for this sample so that we can have an
// InArgument, and also do everything without XAML at all
DynamicActivity codeWorkflow = new DynamicActivity();
codeWorkflow.Name = "MyScenario.MyDynamicActivity";
foreach (var key in inputs.Keys)
{
DynamicActivityProperty property = new DynamicActivityProperty();
property.Name = key;
property.Type = typeof(InArgument<Dictionary<string,object>>);
codeWorkflow.Properties.Add(property);
}
codeWorkflow.Implementation = () => new WriteLine
{
Text = new CSharpValue<string>
{
ExpressionText = "\"hello ! \" + InArguments[\"userName\"].ToString()"
},
};
Compile(codeWorkflow);
WorkflowInvoker.Invoke(codeWorkflow,
new Dictionary<string, object>
{
{ "InArguments", inputs}
});
Console.ReadLine();
}
编译方法为:
static void Compile(DynamicActivity dynamicActivity)
{
TextExpressionCompilerSettings settings = new TextExpressionCompilerSettings
{
Activity = dynamicActivity,
Language = "C#",
ActivityName = dynamicActivity.Name.Split('.').Last() + "_CompiledExpressionRoot",
ActivityNamespace = string.Join(".", dynamicActivity.Name.Split('.').Reverse().Skip(1).Reverse()),
RootNamespace = null,
GenerateAsPartialClass = false,
AlwaysGenerateSource = true,
};
TextExpressionCompilerResults results =
new TextExpressionCompiler(settings).Compile();
if (results.HasErrors)
{
throw new Exception("Compilation failed.");
}
ICompiledExpressionRoot compiledExpressionRoot =
Activator.CreateInstance(results.ResultType,
new object[] { dynamicActivity }) as ICompiledExpressionRoot;
CompiledExpressionInvoker.SetCompiledExpressionRootForImplementation(
dynamicActivity, compiledExpressionRoot);
}