我已经创建了以下WF活动来测试用一组变量执行(vb)表达式的概念'可以在该表达式中访问。
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:以下错误 处理工作流树时遇到: &#39; VisualBasicValue&#39;:编译器错误遇到处理 表达&#34; var.Id = 2&#34;。 &#39;无功&#39;没有宣布。它可能无法访问 由于其保护水平。
我无法理解为什么变量(var)对于表达式不可用,因为它在父母的声明中声明了#var;&#39;表达式执行上下文的活动(是在ExpressionEncapsulationActivity活动中创建的Assign子活动)。
值得注意的是,如果传入的表达式不引用变量(例如&#34; 1 = 1&#34;),则测试有效。有趣的是,如果我使用Sequence
活动,设置其变量并向其添加Assign
子活动,我可以使这种表达有效评估表达式。
答案 0 :(得分:0)
看起来我的问题源于对私人和公共'元数据'之间的区别缺乏了解。
更多相关内容:
前者(私有)使用AddIXXXX形式的元数据方法注册,后者使用AddXXX形式的方法(例如AddChild)注册。
私人和公共'区域'混合不好(根本没有?)。例如,私人子活动(我上面提到的类型中的类型)无法访问公共变量。在我的问题测试中设置的变量(在属性Variables中)是公共的。
关于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
}
所有人都有乐趣!