2016-11-22 7 views
0

私は、(vb)式をその中でアクセス可能な変数のセットで実行するという概念をテストするために作成した以下のWFアクティビティを持っています表現。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

(プライベート)前者は、フォームAddXXX(例えばAddChildは)の方法とフォームAddImplementationXXX後者のメタデータメソッドに登録されています。

プライベートとパブリックの「ゾーン」はよく混合されません。プライベートな子アクティビティ(私の質問の型の)は、例えばパブリック変数にアクセスすることはできません。そして、私の質問のテストで設定されている変数(プロパティの変数)は公開されています。

base.CacheMetadata()で何が起こっているかについても気をつけることができますが、(そして私は訂正中です)リフレクションを使って登録する適切なプロパティを見つけます。子や変数をどのように登録するかをもっと制御したいのであれば、base.CacheMetadata()を呼び出さない方が良い場合がよくあります。

私が遭遇したもう一つのスパナーは、アクティビティ内で定義されたパブリック変数がそのアクティビティ内でアクセスできないということでした。それらは(パブリック)子アクティビティのみからアクセス可能です。これにより、結果を返すpublic子アクティビティ(NativeActivityなど)が難しくなり、Resultプロパティに結果が返されます。自然なアプローチは、 'Result'(OutArgument)を変数にバインドしてその結果を抽出し、その結果を取り出すためにvariable.Get(context)を使用することです。

これはできません。 'result'パラメータをとり、それを使用する 'Completed'イベントメソッドを実装する必要があります。例:

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

楽しかったです。

関連する問題