2016-11-22 55 views
0

我有以下WF活動,我已創建這些活動來測試執行(vb)表達式的一組「變量」表達。Windows Workflow自定義活動:評估引用變量的表達式時出錯

public class ExpressionEncapsulationActivity : NativeActivity<bool> 
    { 
    private readonly Collection<Variable> _variables = new Collection<Variable>(); 
    private readonly Collection<Activity> _activities = new BindingList<Activity>(); 
    private Assign _expressionEvaluationChild { get; set; } 
    private Variable<bool> _expressionResultVariable; 

    public Collection<Variable> Variables { get { return _variables; } } 
    public InArgument<bool> Expression { get; set; } 

    protected override void CacheMetadata(NativeActivityMetadata metadata) 
    { 
     base.CacheMetadata(metadata); 
     DisplayName = "Expression Encapsulation"; 

     metadata.SetVariablesCollection(Variables); 
     metadata.SetChildrenCollection(_activities); 

     _expressionResultVariable = new Variable<bool>("evalResult"); 
     _expressionEvaluationChild = new Assign() 
     { 
     DisplayName = "Expression Encapsulation Assign", 
     To = new OutArgument<bool>(_expressionResultVariable), 
     Value = new InArgument<bool>((ctx) => Expression.Get(ctx)) 
     }; 

     metadata.AddImplementationVariable(_expressionResultVariable); 
     metadata.AddImplementationChild(_expressionEvaluationChild); 
    } 

    protected override void Execute(NativeActivityContext context) 
    { 
     context.ScheduleActivity(_expressionEvaluationChild, OnExpressionEvaluationComplete); 
    } 

    protected void OnExpressionEvaluationComplete(NativeActivityContext context, ActivityInstance completedActivity) 
    { 
     Result.Set(context, _expressionResultVariable.Get(context)); 
    } 

    } 

而且我想測試活動如下: (類ForEachActivityItem簡單,上有一個id屬性)

var testVarItem = new ForEachActivityItem() 
    { 
    Id = 2 
    }; 
    var workflow = new ExpressionEncapsulationActivity() 
    { 
    Variables = 
    { 
     new Variable<ForEachActivityItem>("var", (ctx) => testVarItem) 
    }, 
    Expression = new InArgument<bool>(new VisualBasicValue<bool>("var.Id = 1")) 
    }; 
    var result = WorkflowInvoker.Invoke(workflow); 
    Assert.IsFalse(result, "Test #1"); 

但這種測試引發錯誤:

System.Activities.InvalidWorkflowException: The following errors were encountered while processing the workflow tree: 'VisualBasicValue': Compiler error(s) encountered processing expression "var.Id = 2". 'var' is not declared. It may be inaccessible due to its protection level.

我不明白爲什麼變量(var)不可用於表達式,因爲它在表達式的執行上下文的「父」活動中聲明(即Assign ch在ExpressionEncapsulationActivity活動內創建的活動活動)。

可能值得注意的是,如果傳入的表達式不引用變量(例如「1 = 1」),則測試可以工作。同樣有趣的是,如果我使用Sequence活動,設置其變量並向其添加一個Assign子活動來評估表達式,則我可以使用獲得此類表達式。

回答

0

看起來我的問題源於對私人和公共「元數據」之間的區別缺乏瞭解。

More on this here:

https://stackoverflow.com/questions/36068737/how-to-call-an-activity-inside-another-activity-in-microsoft-workflow

前者(私有)與以下形式的AddImplementationXXX元數據的方法和使用形式AddXXX(例如的AddChild)的方法,後者註冊。

私人和公共'區'混合不好(根本?)。私人兒童活動(在我上面的問題中的類型)不能訪問公共變量。在我的問題測試中設置的變量(屬性變量)是公開的。

還有很多需要注意的是base.CacheMetadata()中發生了什麼(我正在糾正中說)使用反射來找到合適的屬性來爲您註冊。如果你想更多地控制子類和變量的註冊方式,通常最好不要調用base.CacheMetadata()。

我遇到的另一個'扳手'是在活動中定義的公共變量在該活動中不可訪問 - 它們只能由(公共)子活動訪問。這使得執行結果返回的公共子活動(例如NativeActivity)非常棘手,該活動返回Result屬性中的結果。自然的方法是想通過將'Result'(一個OutArgument)綁定到一個變量來提取結果,然後使用variable.Get(context)來提取結果。

你不能這樣做。你需要實現一個'Completed'事件方法,它接受一個'result'參數並使用它。例如:

private void OnFuncEvaluationComplete(NativeActivityContext context, 
        ActivityInstance completedinstance, bool result) 
{ 
    Result.Set(context, result); // Set my result to that returned by the child activity 
} 

有趣的是所有的!