使用参数在两个自定义活动之间共享CorrelationHandle
本文关键字:自定义 两个 活动 之间 CorrelationHandle 共享 参数 | 更新日期: 2023-09-27 18:12:40
我正在构建自定义活动,第一个活动包含ReceiveSendReply活动和其他一些活动。在这个活动中,我正在创建工作流实例。我想给OutArgument分配一个初始化的CorrelationHandle。它将被分配给外部共享变量。
在另一个活动中,我有另一个ReceiveSendReply活动,它将恢复由上述活动创建的实例。在第二个活动中,我有CorrelationHandle作为InArgument。我将用外部共享的correlationHandle变量赋值这个InArgument。
当我执行此工作流服务时,第一个操作执行时没有任何问题,它填充相关键,并且我在响应中接收该相关键。当我使用接收到的关联键执行第二个活动时,服务返回以下异常:
"实例键'45f99690-2829-3126-0782-99033212633c'没有关联到实例,因此InstancePersistenceCommand的执行被中断。发生这种情况可能是因为实例或键已被清理,或者因为键无效。如果生成密钥的消息在错误的时间发送或包含不正确的相关数据,则密钥可能无效。"
我想知道如何通过使用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))
}
},
}
},
}
};
}
}
我们应该使用句柄作为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))
}
},
}
},
}
}
}
}