【问题标题】:Dynamically setting variables in outer scope from WF 4 activity从 WF 4 活动动态设置外部范围内的变量
【发布时间】:2010-12-02 22:17:55
【问题描述】:

如何在 .NET 4 下的 Windows Workflow Foundation 活动中动态设置父范围的变量值?

失败的尝试(在 Sequence 具有名为 Test 的 int 变量的工作流中删除 Sequence 活动):

public sealed class CodeActivity1 : NativeActivity
{
    protected override void CacheMetadata(NativeActivityMetadata metadata)
    {
        _locationReferences =
            metadata.Environment.GetLocationReferences().ToList();

        base.CacheMetadata(metadata);
    }

    protected override void Execute(NativeActivityContext context)
    {
        LocationReference locationReference =
            _locationReferences.Find(
                x => x.Name == "Test" && x.Type == typeof (int));

        if (locationReference != null)
        {
            Console.WriteLine(
                locationReference.Name + " " + locationReference.Type);

            // Blows up here.
            Location location = locationReference.GetLocation(context);
            location.Value = 5;
        }
    }

    private List<LocationReference> _locationReferences;
}

这会导致:

System.InvalidOperationException 是 用户代码未处理
消息=活动 '1.2: CodeActivity1' 无法访问此变量,因为它 在活动范围内声明 '1.1:序列'。一个活动只能 访问自己的实现 变量。

它确实找到了变量;它只是无法获取或设置其值。

变量名(上例中的“Test”)要到运行时才能知道。

【问题讨论】:

    标签: workflow-foundation workflow-foundation-4


    【解决方案1】:

    处理此问题的常规方法是定义 OutArgument 并在工作流设计器中将 OutArgument 绑定到您的变量。在活动中,您只使用参数。使用 NativeActivity 会为您提供一个名为 Result 的 OutArgument,但只需添加 OUTArgument 的属性就可以了。

    另一个好处是您不需要知道“神奇”的变量名称来存储结果。

    更新,因为下面评论中的代码不可读。

    尝试在它爆炸的行之前添加以下内容:

    var pi = context.GetType().GetProperty("AllowChainedEnvironmentAccess", BindingFlags.NonPublic | BindingFlags.Instance); 
    pi.SetValue(context, true, null); 
    

    完全不支持,请谨慎使用:-)

    【讨论】:

    • 我要求客户没有硬编码的工作流程知识。我们习惯于 BPM,您可以通过传入名称、值对来初始化字段、询问正在运行的流程以获取字段列表然后设置它们等来创建流程。它更加灵活、可发现和解耦运行时安全的成本。从 BPM 转到 WF 就像从动态类型语言转到静态类型语言一样。我认为我们有两个选择:使用 Dictionary 类型的变量伪造它或询问 WSDL。
    • 我想我完全误解了你的问题。我的印象是您尝试使用特定的工作流变量,而这与 WSDL 和 WCF 客户端无关。 WCF 请求参数只是接收参数的结果。如何将结果与内部工作流变量联系起来,甚至忽略值,对客户端应用程序来说是完全透明的。
    • @Maurice - 我试图让示例保持简单。我希望 Receive 参数是一个固定类型,具有名称、值对的集合。调用时,它将动态更新范围内具有匹配名称的任何变量。
    • 尝试在它爆炸的行之前添加以下内容: var pi = context.GetType().GetProperty("AllowChainedEnvironmentAccess", BindingFlags.NonPublic | BindingFlags.Instance); pi.SetValue(context, true, new object[0]);完全不支持所以小心使用:-)
    • 因为根据 Reflector 这不是索引属性,它应该是 pi.SetValue(context, true, null)。无论哪种方式,它都有效!我会尽量避免在生产中这样做。再次感谢! :)
    猜你喜欢
    • 2018-11-30
    • 2018-06-04
    • 1970-01-01
    • 2014-05-12
    • 2013-09-23
    • 1970-01-01
    • 2021-08-18
    • 2011-08-09
    相关资源
    最近更新 更多