使用参数在两个自定义活动之间共享CorrelationHandle

时间:2011-10-27 19:29:40

标签: c# c#-4.0 workflow-foundation workflow-foundation-4 workflowservice

我正在构建自定义活动,第一个活动包含ReceiveSendReply活动以及其他一些活动。在此活动中,我正在创建工作流实例。我想为OutArgument分配一个初始化的CorrelationHandle。将分配给外部共享变量。

在另一个活动中,我有另一个ReceiveSendReply活动,它将恢复上述活动创建的实例。在第二个活动中,我将CorrelationHandle作为InArgument。我将为此InArgument分配外部共享correlationHandle varriable。

当我执行此工作流服务时,第一个操作执行没有任何问题,它填充相关键,我在响应中收到该相关键。当我使用收到的相关键执行第二个活动时,服务返回时出现以下异常:

“InstancePersistenceCommand的执行被中断,因为实例密钥'45f99690-2829-3126-0782-99033212633c'未与实例关联。这可能是因为实例或密钥已被清理,或因为密钥如果生成的消息是在错误的时间发送的,或者包含错误的相关数据,则该密钥可能无效。“

我想知道如何使用OutArgument和InArguments在两个自定义活动之间共享CorrelationHandle?

public sealed class Create : Activity
{
    public Create()
    {
        Implementation = new Func<Activity>(CreateBody);
    }

    public string ServiceContract { get; set; }

    public string Operation { get; set; }

    [RequiredArgument]
    public OutArgument<CorrelationHandle> CorrelationHandle { get; set; }

    Activity CreateBody()
    {
        // variables declaration. 
        var requestContent = new Variable<string>();
        var operationResponseParam = new Variable<OperationResponseParam>();
        var correlationKey = new Variable<string>();
        var correlationHandle = new Variable<CorrelationHandle>();

        Receive receiveRequest;

        return new Sequence
        {
            Variables = { correlationHandle, correlationKey }, 
            Activities = 
            {
                {receiveRequest = new Receive()
                {
                    ServiceContractName = ServiceContract,
                    OperationName = Operation,
                    CanCreateInstance = true,
                    Content = new ReceiveMessageContent
                    {
                        Message = new OutArgument<string>(ctx => operationRequestParam.Get(ctx))
                    },
                }},

                new Assign<string>
                {
                    To = new OutArgument<string>(ctx => correlationKey.Get(ctx)),
                    Value = new InArgument<string>(ctx => Guid.NewGuid().ToString())
                },

                new Assign<ApplicationDataList>
                {
                    To = new ArgumentReference<ApplicationDataList>("AppData"),
                    Value = new InArgument<ApplicationDataList>(ctx =>appData.Get(ctx))
                },

                new Assign<OperationResponseParam>
                {
                    To = new OutArgument<OperationResponseParam>(ctx => operationResponseParam.Get(ctx)),
                    Value = new InArgument<OperationResponseParam>
                    {
                        Expression = new BuildResponse()
                        {
                            CorrelationKey = new InArgument<string>(correlationKey),
                        }
                    }
                },

                new SendReply
                {
                    Request = receiveRequest,
                    Content = new SendMessageContent
                    {
                        Message = new InArgument<OperationResponseParam>(ctx => operationResponseParam.Get(ctx))
                    },

                    CorrelationInitializers =
                    {
                        new QueryCorrelationInitializer
                        {
                            CorrelationHandle =  new InArgument<CorrelationHandle>(correlationHandle),
                            MessageQuerySet = new MessageQuerySet
                            {
                                {
                                    "CorrelationKey", new XPathMessageQuery("sm:header()/tempuri:CorrelationKey")
                                }
                            }
                        }
                    }
                },

                new Assign<CorrelationHandle>
                {
                    To = new ArgumentReference<CorrelationHandle>("CorrelationHandle"),
                    Value = new InArgument<CorrelationHandle>(ctx =>correlationHandle.Get(ctx))
                },
            }
        };
    }
}


public sealed class Wait : Activity
{
    public Wait()
    {
        Implementation = new Func<Activity>(CreateBody);
    }

    public string ServiceContract { get; set; }

    public string Operation { get; set; }

    [RequiredArgument]
    public InArgument<CorrelationHandle> CorrelationHandle { get; set; }

    Activity CreateBody()
    {
        // variables declaration. 

        var operationRequestParam = new Variable<OperationRequestParam>();
        var operationResponseParam = new Variable<OperationResponseParam>();
        var correlationHandle = new Variable<CorrelationHandle>();
        Receive receiveRequest;

        return new Sequence
        {
            Variables = { correlationHandle },
            Activities =
            {
                new Sequence
                {
                    Variables = {operationRequestParam, operationResponseParam },

                    Activities = 
                    {
                        {receiveRequest =new Receive()
                        {
                            ServiceContractName = ServiceContract,
                            OperationName = Operation,
                            CanCreateInstance = false,
                            CorrelatesWith = new InArgument<CorrelationHandle>(ctx => CorrelationHandle.Get(ctx)),
                            CorrelatesOn = new MessageQuerySet
                            {
                                { "CorrelationKey", new XPathMessageQuery("sm:header()/tempuri:CorrelationKey")}
                            },

                            //parameters for receive
                            Content = new ReceiveMessageContent
                            {
                                Message = new OutArgument<OperationRequestParam>(ctx => operationRequestParam.Get(ctx))
                            },
                        }},


                        new Assign<OperationResponseParam>
                        {
                            To = new OutArgument<OperationResponseParam>(operationResponseParam),
                            Value = new InArgument<OperationResponseParam>
                            {
                                Expression = new BuildResponse()
                                {
                                    ApplicationData = new InArgument<ApplicationDataList>(ctx => appData.Get(ctx)),
                                }
                            }
                        },

                        new SendReply
                        {
                            Request = receiveRequest,
                            Content = new SendMessageContent
                            {
                                Message = new InArgument<OperationResponseParam>(ctx => operationResponseParam.Get(ctx))
                            }
                        },
                    }
                },
            }
        };
    }
}

1 个答案:

答案 0 :(得分:1)

我们应该使用句柄作为InArgument,并且InitializeCorrelation将修改引用句柄的对象。所以在我的两个活动中,我必须在第一个中使用InArgument而不是OutArgument,在第二个中使用InArgument。

public sealed class Create : Activity
{
    public Create()
    {
        Implementation = new Func<Activity>(CreateBody);
    }

    public string ServiceContract { get; set; }

    public string Operation { get; set; }

    [RequiredArgument]
    public InArgument<CorrelationHandle> CorrelationHandle { get; set; }

    Activity CreateBody()
    {
        // variables declaration. 
        var operationRequestParam = new Variable<OperationRequestParam>();
        var appData = new Variable<ApplicationDataList>();
        var operationResponseParam = new Variable<OperationResponseParam>();
        var correlationKey = new Variable<string>();


        Receive receiveRequest;

        return new Sequence
        {
            Variables = { correlationKey }, 
            Activities = 
            {
                {receiveRequest = new Receive()
                {
                    ServiceContractName = ServiceContract,
                    OperationName = Operation,
                    CanCreateInstance = true,
                    //parameters for receive
                    Content = new ReceiveMessageContent
                    {
                        Message = new OutArgument<string>(ctx => operationRequestParam.Get(ctx))
                    },
                }},

                // Assign a unique identifier to the correlation key.
                new Assign<string>
                {
                    To = new OutArgument<string>(ctx => correlationKey.Get(ctx)),
                    Value = new InArgument<string>(ctx => Guid.NewGuid().ToString())
                },

                new Assign<OperationResponseParam>
                {
                    To = new OutArgument<OperationResponseParam>(ctx => operationResponseParam.Get(ctx)),
                    Value = new InArgument<OperationResponseParam>
                    {
                        Expression = new BuildResponse()
                        {
                            CorrelationKey = new InArgument<string>(correlationKey),
                        }
                    }
                },

                new SendReply
                {
                    Request = receiveRequest,
                    Content = new SendMessageContent
                    {
                        Message = new InArgument<string>(ctx => operationResponseParam.Get(ctx))
                    },

                    CorrelationInitializers =
                    {
                        new QueryCorrelationInitializer
                        {
                            CorrelationHandle =  new InArgument<CorrelationHandle>(ctx => CorrelationHandle.Get(ctx)),
                            MessageQuerySet = new MessageQuerySet
                            {
                                {
                                    "CorrelationKey", new XPathMessageQuery("sm:header()/tempuri:CorrelationKey")
                                }
                            }
                        }
                    }
                },
            }
        };
    }
}

public sealed class Wait : Activity
{
    static Wait()
    {
        AttributeTableBuilder builder = new AttributeTableBuilder();
        builder.AddCustomAttributes(typeof(Wait), "EscalationData", new EditorAttribute(typeof(EscalationDataEditor), typeof(DialogPropertyValueEditor)));
        MetadataStore.AddAttributeTable(builder.CreateTable());
    }

    public Wait()
    {
        Implementation = new Func<Activity>(CreateBody);
    }

    public EscalationInfoList EscalationData { get; set; }

    public string ServiceContract { get; set; }

    public string Operation { get; set; }

    [RequiredArgument]
    public InArgument<CorrelationHandle> CorrelationHandle { get; set; }

    Activity CreateBody()
    {
        // variables declaration. 
        var appData = new Variable<ApplicationDataList>();
        var operationRequestParam = new Variable<OperationRequestParam>();
        var operationResponseParam = new Variable<OperationResponseParam>();

        Receive receiveRequest;

        return new Sequence
        {
            Activities =
            {
               new Sequence
               {
                    Variables = {operationRequestParam, operationResponseParam },

                    Activities = 
                    {
                        {receiveRequest =new Receive()
                        {
                            ServiceContractName = ServiceContract,
                            OperationName = Operation,
                            CanCreateInstance = false,
                            CorrelatesWith = new InArgument<CorrelationHandle>(ctx => CorrelationHandle.Get(ctx)),
                            CorrelatesOn = new MessageQuerySet
                            {
                                { "CorrelationKey", new XPathMessageQuery("sm:header()/tempuri:CorrelationKey")}
                            },

                            //parameters for receive
                            Content = new ReceiveMessageContent
                            {
                                Message = new OutArgument<OperationRequestParam>(ctx => operationRequestParam.Get(ctx))
                            },
                        }},

                        new SendReply
                        {
                            Request = receiveRequest,
                            Content = new SendMessageContent
                            {
                                Message = new InArgument<OperationResponseParam>(ctx => operationResponseParam.Get(ctx))
                            }
                        },
                    }
                },
            }
        }
    }
}