子活动的自定义活动设置参数

时间:2011-04-04 10:01:08

标签: .net workflow-foundation-4

我正在尝试为承载子活动的WF4创建自定义活动,并将一些参数传递给其子活动。我在下面附上我的活动的简化版本(父母和孩子)

public class Child : CodeActivity
{
    public InArgument<Dictionary<string, object>> Data;

    protected override void Execute(CodeActivityContext context)
    {
        Dictionary<string, object> data = Data.Get(context);

        //Some operations on the input data
    }
}


 public class Parent : NativeActivity
{
    public InArgument<int> Value1 { get; set; }

    public InArgument<string> Value2 { get; set; }

    public Child Body { get; set; }


    protected override void Execute(NativeActivityContext context)
    {
        int value1 = Value1.Get(context);
        string value2 = Value2.Get(context);

        Dictionary<string, object> data = new Dictionary<string, object>();
        data.Add("value1", value1);
        data.Add("value2", value2);

        context.SetValue(Body.Data, data);

        context.ScheduleActivity(this.Body);
    }


    protected override void CacheMetadata(NativeActivityMetadata metadata)
    {
        Body = new Child();

        base.CacheMetadata(metadata);
    }
}

当工作流程执行到达活动的Execute方法时,Child活动的Data参数为null。

有人可以,请指点我们如何在这两项活动之间传递论据?

3 个答案:

答案 0 :(得分:6)

虽然使用额外变量的方法起作用,但是使用某些输入调度子项的“官方”方法是在ActivityAcytion中使用,或者如果您还想要使用ActivityFunc的结果。

我担心代码不会变得更简单或更容易理解,但为了完整起见,我只是决定添加它。

public class Child : CodeActivity<object>
{
    public InArgument<Dictionary<string, object>> Data { get; set; }

    protected override object Execute(CodeActivityContext context)
    {
        Dictionary<string, object> data = Data.Get(context);

        foreach (var item in data)
        {
            Console.WriteLine(item);
        }

        return "Some result";
    }
}



public class Parent : NativeActivity<object>
{
    public InArgument<int> Value1 { get; set; }
    public InArgument<string> Value2 { get; set; }

    public ActivityFunc<Dictionary<string, object>, object> Body { get; set; }

    protected override void Execute(NativeActivityContext context)
    {
        int value1 = Value1.Get(context);
        string value2 = Value2.Get(context);

        Dictionary<string, object> data = new Dictionary<string, object>();
        data.Add("value1", value1);
        data.Add("value2", value2);

        context.ScheduleFunc<Dictionary<string, object>, object>(Body, data, ChildCompletionCallback);
    }


    protected override void CacheMetadata(NativeActivityMetadata metadata)
    {
        var arg = new DelegateInArgument<Dictionary<string, object>>();

        Body = new ActivityFunc<Dictionary<string, object>, object>
        {
            Argument = arg,
            Handler = new Child() { Data = arg }
        };

        base.CacheMetadata(metadata);
    }

    private void ChildCompletionCallback(NativeActivityContext context, ActivityInstance completedInstance, object result)
    {
        //Set the output for the parent activity at the completion of the child activity
        this.Result.Set(context, result);
    }
}

答案 1 :(得分:2)

我还需要通过父活动从子活动返回结果。为此,我使用ScheduleActivity方法和CompletionCallback参数。我附加了包含out参数集的Parent / Child示例活动,也许有人在某个时候需要它:)

父:

public class Parent : NativeActivity<object>
{
    public InArgument<int> Value1 { get; set; }
    public InArgument<string> Value2 { get; set; }
    private Variable<Dictionary<string, object>> SomeVariable { get; set; } // intermediate variable

    private Child Body { get; set; }

    public Parent()
    {
        this.SomeVariable = new Variable<Dictionary<string, object>>("SomeVariable");

        this.Body = new Child();
        this.Body.Data = new InArgument<Dictionary<string, object>>(SomeVariable);
    }

    protected override void Execute(NativeActivityContext context)
    {
        int value1 = Value1.Get(context);
        string value2 = Value2.Get(context);

        Dictionary<string, object> data = new Dictionary<string, object>();
        data.Add("value1", value1);
        data.Add("value2", value2);

        this.SomeVariable.Set(context, data);

        context.ScheduleActivity(this.Body, ChildCompletionCallback);
    }

    protected override void CacheMetadata(NativeActivityMetadata metadata)
    {
        base.CacheMetadata(metadata);

        // needs to be cached as implementation child and variable (Body and SomeVariable must be declared as private then)
        metadata.AddImplementationChild(this.Body);
        metadata.AddImplementationVariable(SomeVariable);
    }

    private void ChildCompletionCallback<TResult>(NativeActivityContext context, ActivityInstance completedInstance, TResult result)
    {
        //Set the output for the parent activity at the completion of the child activity
        this.Result.Set(context, result);
    }
}

子:

public class Child : CodeActivity<object>
{
    public InArgument<Dictionary<string, object>> Data { get; set; }

    protected override object Execute(CodeActivityContext context)
    {
        Dictionary<string, object> data = Data.Get(context);

        return "Some result";
    }
}

答案 2 :(得分:1)

可能无法直接在Execute方法中设置输入参数的值。必须引入中间变量。 Child.Data参数连接到此变量并且在Parent.Execute方法中。

父:

public class Parent : NativeActivity
{
    public InArgument<int> Value1 { get; set; }
    public InArgument<string> Value2 { get; set; }
    private Variable<Dictionary<string, object>> SomeVariable { get; set; } // intermediate variable

    private Child Body { get; set; }

    public Parent()
    {
        this.SomeVariable = new Variable<Dictionary<string, object>>("SomeVariable");

        this.Body = new Child();
        this.Body.Data = new InArgument<Dictionary<string, object>>(SomeVariable);
    }

    protected override void Execute(NativeActivityContext context)
    {
        int value1 = Value1.Get(context);
        string value2 = Value2.Get(context);

        Dictionary<string, object> data = new Dictionary<string, object>();
        data.Add("value1", value1);
        data.Add("value2", value2);

        this.SomeVariable.Set(context, data);

        context.ScheduleActivity(this.Body);
    }

    protected override void CacheMetadata(NativeActivityMetadata metadata)
    {
        base.CacheMetadata(metadata);

        // needs to be cached as implementation child and variable (Body and SomeVariable must be declared as private then)
        metadata.AddImplementationChild(this.Body);
        metadata.AddImplementationVariable(SomeVariable);
    }
}

子:

public class Child : CodeActivity
{
    // Must be declared as property.
    public InArgument<Dictionary<string, object>> Data
    {
        get;
        set;
    }

    protected override void Execute(CodeActivityContext context)
    {
        var data = this.Data.Get(context);
    }
}

这不是一个很好的解决方案但我在WF4中几乎看不到任何好处:)。