Jay*_*van 5 workflow-foundation-4
我有一个外部活动,它有一个主体,您可以将其他活动拖到上面。然后我有几个内部活动,它们必须是外部活动的后代。我想添加设计时验证以确保内部放置在外部内。
我听说我“可以在验证步骤中使用 System.Activities.Validation.GetParentChain 枚举活动的所有父项”。但即使在阅读了该类的文档之后,我也不知道如何使用它。
我想我在内部类的 CacheMetadata 中使用它。我想使用 foreach(varparents inparentChain) { ... } ,并确保至少一个祖先是 Outer 类型。不知道该怎么做。
谁能解释如何在设计时验证内部活动是外部活动的后代?
正如您通过文档 看到的那样,GetParentChain这是一个常规的CodeActivity. 您可以将其与 结合使用Activity.Constraints。
约束在设计时执行,就像 一样CacheMetadata(),但是您可以访问上下文(当然,此时是ValidationContext )。否则你将无法了解上层活动。
让我们看看我是否正确理解了您的情况以及这个示例是否涵盖了它。基本上,它循环IEnumerable<Activity>返回并检查Inner的父级GetParentChain是否是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"
                        }
                    }
                }
            }
        };
    }
}
如果您想允许多个 Outer,则必须通过数组(使用 ForEach)或多个嵌套的 If 循环来逐一检查它们。
例如,使用多个 if,并继续上面的代码:
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 语句。
我从未测试过的其他选项,但它似乎非常合理,并且因为您可以在约束内使用活动,所以将所有这些逻辑放入活动中,其唯一的工作是检查是否键入外部:
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;
    }
}
这样就可以通过代码来完成。
好吧,我想你明白了!
| 归档时间: | 
 | 
| 查看次数: | 1217 次 | 
| 最近记录: |