代码之家  ›  专栏  ›  技术社区  ›  Terrance

工作流基础4-即使Execute方法显示为true,ActivityFunc<bool>的结果始终为false

  •  1
  • Terrance  · 技术社区  · 14 年前

    Ello,我遇到了一个定制活动的问题,该活动对“ActivityFunc”执行求值并返回false,即使它在Execute中被求值为true。 这是我的活动

    
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Activities;
    using System.ComponentModel;
    using System.Activities.Presentation;
    
    namespace SomeActivities
    {
        /// 
        /// Root of any number of activities used to check for a specific set of conditions to be true (Trigger Conditions) 
        /// 
        public sealed class Trigger : NativeActivity, IActivityTemplateFactory
        {
            /// 
            /// The initial Condition that determines if the trigger should be scheduled
            /// 
            /// The condition.
            [RequiredArgument]
            public ActivityFunc <bool> Condition { get; set; }
    
            /// 
            /// The resulting action that is scheduled if the Condition is true
            /// 
            /// The child.
            [RequiredArgument]
            public ActivityAction Child { get; set; }
    
            /// 
            /// Gets or sets the value holding whether or not the trigger matches the condition
            /// 
            /// The type of the match.
            public MatchType MatchType{ get; set; }
    
            private CompletionCallback<bool> OnExecutionCompleteCallBack;
    
            protected override void Execute(NativeActivityContext context)
            {
                this.OnExecutionCompleteCallBack = this.OnConditionComplete;
                context.ScheduleFunc<bool>(this.Condition, this.OnExecutionCompleteCallBack);
            }
    
            public void OnConditionComplete(NativeActivityContext context, ActivityInstance instance, bool result)
            {
                if (instance.State == ActivityInstanceState.Canceled)
                {
                    context.Abort();
                    return;
                }
    
                //check if Condition evaluation returns true
                //Always show as false
                if (result)
                {
                    //If so then schedule child Activity
                    context.ScheduleAction(Child);
                }
            }
    
            Activity IActivityTemplateFactory.Create(System.Windows.DependencyObject target)
            {
                return new Trigger()
                {
                    Child = new ActivityAction()
                    {
                        DisplayName = "Trigger Child Action"
                    },
    
                    Condition = new ActivityFunc<bool>()
                    {
                        DisplayName = "Trigger Conditionals",
                        Result = new DelegateOutArgument<bool>()
                    },
                    DisplayName = "Trigger",
                    MatchType = MatchType.Matches,
    
                };
            }
        }
    }
    
    

    更新

    好的,我认为Marice正在讨论在类中使用回调函数,而只是让OnConditionComplete方法指向回调函数。我确实改变了,但没看到改变。如果我能从 ActivityFunc<bool> child 条件当它实际执行或保存它的值之后,这将工作得很好。我对CacheMetadata的元数据做了一些研究,看看是否有什么东西可以让我找到,但到目前为止还没有找到。

    更新2

    ActivityFunc <bool> Condition . 我得检查一下情况有什么问题。不确定这个问题是否应该成为一个新的问题,因为它在技术上还没有解决,但我会考虑把一个测试条件放在一起,如果没有其他东西表明我在哪里。

    更新3

    好的,这是一个简单的例子,我将它用作子活动,它总是返回false,即使在执行过程中它的计算结果为true

    
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Activities;
    using System.Activities.Presentation;
    using System.ComponentModel;
    using System.Drawing;
    
    namespace SomeActivities
    {
        public sealed class DataHandlerTypeName : NativeActivity,IActivityTemplateFactory
        {
            // Define an activity input argument of type string
            [RequiredArgument]
            public InArgument ImportContext { get; set; }
    
            /// 
            /// Gets or sets the handler type name to check.
            /// 
            /// The handler type name to check.
            [RequiredArgument]
            public string HandlerTypeNameToCheck { get; set; }
    
    
            /// 
            /// Performs the trigger check for the matching Data Type Handler Names
            /// 
            /// The context.
            protected override void Execute(NativeActivityContext context)
            {
                var ic = this.ImportContext.Get(context);
    
                if (1==1)
                {
                    //context.SetValue(base.Result, true);
                    Result.Set(context, true);
                }
                else 
                {
                    //context.SetValue(base.Result, true);
                    Result.Set(context, false);
                }
            }
    
            #region IActivityTemplateFactory Members
    
    
            Activity IActivityTemplateFactory.Create(System.Windows.DependencyObject target)
            {
                return new DataHandlerTypeName()
                {
                    ImportContext = this.ImportContext,
                    HandlerTypeNameToCheck = "Default"
                };
            }
    
            #endregion
        }
    }
    
    
    
    2 回复  |  直到 14 年前
        1
  •  1
  •   user1228 user1228    14 年前

    你好,有人谁我从来没有见过,只是碰巧分享我的IP。

    要么你正在使用的活动的DLL不是最新的,要么工作流定义已经过时,不能保存你认为它所做的事情。或者完全不同。

    我已经精简了你的代码并将其压缩成一个示例项目。我们想在这里看到它:

    public sealed class AnTrigger : NativeActivity<bool>
    {
        public bool ResultToSet { get; set; }
    
        protected override void Execute(NativeActivityContext context)
        {
            Result.Set(context, ResultToSet);
        }
    }
    

    很简单,不是吗?这是计算此条件的主机,如果返回true,则运行单个子活动。注意,我正在Create方法中构造活动,因此不必创建编辑器。

    public sealed class AnTriggerHost : NativeActivity, IActivityTemplateFactory
    {
        public ActivityFunc<bool> Condition { get; set; }
        public ActivityAction Child { get; set; }
    
        protected override void Execute(NativeActivityContext context)
        {
            context.ScheduleFunc(Condition, OnConditionComplete);
        }
    
        private void OnConditionComplete(
            NativeActivityContext context, 
            ActivityInstance completedInstance, 
            bool result)
        {
            if (result)
                context.ScheduleAction(Child);
        }
    
        Activity IActivityTemplateFactory.Create(System.Windows.DependencyObject target)
        {
            // so I don't have to create UI for these, here's a couple samples
            // seq is the first child and will run as the first AnTrigger is configured to return true
            // so the first trigger evals to true and the first child runs, which
            var seq = new Sequence
            {
                DisplayName = "Chief Runs After First Trigger Evals True"
            };
            // prints this message to the console and
            seq.Activities.Add(new WriteLine { Text = "See this?  It worked." });
            // runs this second trigger host, which 
            seq.Activities.Add(
                new AnTriggerHost
                {
                    DisplayName = "This is the SECOND host",
                    Condition = new ActivityFunc<bool>
                    {
                        // will NOT be triggered, so you will never see
                        Handler = new AnTrigger
                        {
                            ResultToSet = false,
                            DisplayName = "I return false guize"
                        }
                    },
                    Child = new ActivityAction
                    {
                        // this activity write to the console.
                        Handler = new WriteLine
                        {
                            Text = "you won't see me"
                        }
                    }
                });
    
            return new AnTriggerHost
            {
                DisplayName = "This is the FIRST host",
                Condition = new ActivityFunc<bool>
                {
                    Handler = new AnTrigger
                    {
                        ResultToSet = true,
                        DisplayName = "I return true!"
                    }
                },
                Child = new ActivityAction
                {
                    Handler = seq
                }
            };
        }
    }
    

    将这两个放到工作流控制台应用程序中,并将AnTriggerHost放到工作流中。设置几个断点,看着它飞起来。以下是工作流xaml:

      <local:AnTriggerHost DisplayName="This is the FIRST host" >
        <local:AnTriggerHost.Child>
          <ActivityAction>
            <Sequence DisplayName="Chief Runs After First Trigger Evals True">
              <WriteLine Text="See this?  It worked." />
              <local:AnTriggerHost DisplayName="This is the SECOND host">
                <local:AnTriggerHost.Child>
                  <ActivityAction>
                    <WriteLine Text="you won't see me" />
                  </ActivityAction>
                </local:AnTriggerHost.Child>
                <local:AnTriggerHost.Condition>
                  <ActivityFunc x:TypeArguments="x:Boolean">
                    <local:AnTrigger DisplayName="I return false guize" ResultToSet="False" />
                  </ActivityFunc>
                </local:AnTriggerHost.Condition>
              </local:AnTriggerHost>
            </Sequence>
          </ActivityAction>
        </local:AnTriggerHost.Child>
        <local:AnTriggerHost.Condition>
          <ActivityFunc x:TypeArguments="x:Boolean">
            <local:AnTrigger DisplayName="I return true!" ResultToSet="True" />
          </ActivityFunc>
        </local:AnTriggerHost.Condition>
      </local:AnTriggerHost>
    


    供将来参考。。。当这种情况发生在我身上,原因是我 Result 在IActivityTemplateFactory的Create方法中

    Activity IActivityTemplateFactory.Create(System.Windows.DependencyObject target)
    {
        return new Child
        {
            InputText = new InArgument<string>(
                new VisualBasicValue<string>(Parent.InputTextVariable)),
            // the following demonstrates what NOT to do in the Create method. 
            // this BREAKS your ActivityFunc, which will ALWAYS return default(T)
            // DO NOT SET Result AT ANY TIME OR IN ANY PLACE
            // BEGIN ERROR
            Result = new OutArgument<string>()
            // END ERROR
        };
    }
    

    <!--If you see ActivityFunc.Result in your workflow, DELETE IT -->
    <ActivityFunc.Result>
      <DelegateOutArgument x:TypeArguments="x:String" />
    </ActivityFunc.Result>
    
        2
  •  1
  •   Maurice    14 年前

    ScheduleFunc始终采用ActivityFunc,其中条件定义为ActivityFunc。不确定非泛型ActivityFunc来自何处。CompletionCallback也应该是CompletionCallback。

    我使用的测试代码:

    IActivityTemplateFactory factory = new Trigger();
    var trigger = (Trigger)factory.Create(null);
    trigger.Condition.Handler = new AlwaysTrue();
    trigger.Child.Handler = new WriteLine()
    {
        Text = "Its true."
    };
    WorkflowInvoker.Invoke(trigger);
    
    class AlwaysTrue : CodeActivity<bool>
    {
        protected override bool Execute(CodeActivityContext context)
        {
            return true;
        }
    }
    

    Activity IActivityTemplateFactory.Create(System.Windows.DependencyObject target)
    {
        return new Trigger()
        {
            Child = new ActivityAction()
            {
                DisplayName = "Trigger Child Action"
            },
    
            Condition = new ActivityFunc<bool>()
            {
                DisplayName = "Trigger Conditionals"
            },
            DisplayName = "Trigger"
        };
    }