我有一个外部活动,其中有一个Body,您可以拖动其他活动。然后我有几个内部活动,它必须是外部活动的后代。我想添加设计时验证,以确保将Inner置于外部。
我听说过我“can use System.Activities.Validation.GetParentChain to enumerate all of the parents of an activity during the validation step”。但即使在阅读the documentation for the class后,我也不知道如何使用它。
我认为我在Inner类的CacheMetadata中使用它。我想使用foreach(parentChain中的var ancestor){...},并确保至少有一个祖先是Outer类型。不知道怎么做。
任何人都可以解释如何在设计时验证内部活动是外部活动的后代吗?
答案 0 :(得分:3)
正如您所看到的那样documentation GetParentChain
是常规CodeActivity
。您可以将其与Activity.Constraints
结合使用。
约束在设计时执行,就像CacheMetadata()
一样,但您可以访问上下文(当然, ValidationContext )。否则你将无法知道上层活动。
让我们看看我是否理解你的情况,以及这个例子是否涵盖了它。基本上它会遍历IEnumerable<Activity>
返回的GetParentChain
,并检查 Inner 的父母是否为 Outer 。这样就可以确保 Inner 始终位于 Outer 中。
public sealed class Inner : CodeActivity
{
public Inner()
{
Constraints.Add(MustBeInsideOuterActivityConstraint());
}
protected override void Execute(CodeActivityContext context)
{
// Execution logic here
}
private Constraint<Inner> MustBeInsideOuterActivityConstraint()
{
var activityBeingValidated = new DelegateInArgument<Inner>();
var validationContext = new DelegateInArgument<ValidationContext>();
var parent = new DelegateInArgument<Activity>();
var parentIsOuter = new Variable<bool>();
return new Constraint<Inner>
{
Body = new ActivityAction<Inner, ValidationContext>
{
Argument1 = activityBeingValidated,
Argument2 = validationContext,
Handler = new Sequence
{
Variables =
{
parentIsOuter
},
Activities =
{
new ForEach<Activity>
{
Values = new GetParentChain
{
ValidationContext = validationContext
},
Body = new ActivityAction<Activity>
{
Argument = parent,
Handler = new If
{
Condition = new InArgument<bool>(env =>
object.Equals(parent.Get(env).GetType(), typeof(Outer))),
Then = new Assign<bool>
{
To = parentIsOuter,
Value = true
}
}
}
},
new AssertValidation
{
Assertion = parentIsOuter,
Message = "Inner must be inside Outer"
}
}
}
}
};
}
}
如果你想允许多个Outers,你必须逐个检查它们,通过数组循环(使用ForEach)或多个嵌套的Ifs来萎缩。
例如,使用多个ifs,并继续上面的代码:
Handler = new If
{
Condition = new InArgument<bool>(env =>
object.Equals(parent.Get(env).GetType(), typeof(OuterONE))),
Then = new Assign<bool>
{
To = parentIsOuter,
Value = true
}
Else = new If
{
Condition = new InArgument<bool>(env =>
object.Equals(parent.Get(env).GetType(), typeof(OuterTWO))),
Then = new Assign<bool>
{
To = parentIsOuter,
Value = true
},
Else = new If
{
// and continue with other Outers
}
}
}
简而言之,使用活动的If-then-else语句。
我从未测试过的其他选项,但它似乎很合理,而且因为你可以在约束中使用活动,所以将所有这些逻辑抛出到一个活动中,其唯一的工作是检查类型是否为Outer:
public sealed CheckIfTypeIsOuter<T> : CodeActivity<bool>
{
protected override bool Execute()
{
if (typeof(T) == typeof(Outer1))
return true;
if (typeof(T) == typeof(Outer2))
return true;
if (typeof(T) == typeof(Outer3))
return true;
if (typeof(T) == typeof(Outer4))
return true;
return false;
}
}
这样你就可以通过代码完成。
嗯,我想你明白了!