2016-05-30 100 views
0

我试图使用代码创建工作流程,如here所述。但我无法理解我的结果。我用Class1.cs创建了包含我的工作流代码和 Program.cs的控制台应用程序,工作流托管在WorkflowApplication类中,包括输入。在执行未处理的异常时出现消息 “表达式活动类型'CSharpValue`1'需要编译才能运行。请确保工作流已编译为”“。但我也有 包括用于编译的CompileExpressions方法,如here所述。我提前感谢您的帮助!无法使用WF 4.5中的CSharpValue表达式访问Dictionary

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) 
+0

看来,你必须提供完整的错误消息... [本文](https://blogs.msdn.microsoft.com/tilovell/2012/05/24/wf4-5-using-csharpvaluet-and-csharpreferencet-in-net-4-5-compiling-expressionsand-changes-in-visual-studio-generated-xaml /)可能会有所帮助。 –

回答

0

谢谢马切伊·洛斯先生。最后,我从你提到的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); 
     }