使用VS2012 / .NET 4.5我正在创建一个实现Receive子活动的自定义活动(作为实现子进程)。以下示例中的参数仅固定为一个:Guid类型的OutValue。
我真的很想在ReceiveDone中访问传入参数值的值,因为我需要使用它并在从活动返回之前对其进行转换。请忽略我当前正在使用Guid,它仍然无法使用和InvalidOperationException访问该值:
一个Activity只能获取它拥有的参数的位置。活动'TestActivity'试图获取参数'OutValue'的位置,该参数由活动'等待'拥有 工作流程启动请求[TestActivity的内部]'
我已经尝试了我能想到的一切,但我感到很惊讶。必须有办法做到这一点非常简单吗?
public class TestActivity : NativeActivity<Guid>
{
protected override void CacheMetadata(NativeActivityMetadata metadata)
{
var content = ReceiveParametersContent.Create(new Dictionary<string, OutArgument>()
{
// How to access the runtime value of this inside TestActivity?
{"OutValue", new OutArgument<Guid>()}
});
startReceiver = new Receive()
{
DisplayName = string.Format("Wait for workflow start request [Internal for {0}]", this.DisplayName),
CanCreateInstance = true,
ServiceContractName = XName.Get("IStartService", Namespace),
OperationName = "Start",
Content = content
};
foreach (KeyValuePair<string, OutArgument> keyValuePair in content.Parameters)
{
metadata.AddImportedChild(keyValuePair.Value.Expression);
}
metadata.AddImplementationChild(startReceiver);
}
protected override void Execute(NativeActivityContext context)
{
context.ScheduleActivity(startReceiver, ReceiveDone);
}
private void ReceiveDone(NativeActivityContext context, ActivityInstance completedInstance)
{
var receive = completedInstance.Activity as Receive;
ReceiveParametersContent content = receive.Content as ReceiveParametersContent;
try
{
// This causes InvalidOperationException.
// An Activity can only get the location of arguments which it owns.
// Activity 'TestActivity' is trying to get the location of argument 'OutValue'
// which is owned by activity 'Wait for workflow start request [Internal for TestActivity]'
var parmValue = content.Parameters["OutValue"].Get(context);
}
catch (Exception)
{ }
}
private Receive startReceiver;
private const string Namespace = "http://company.namespace";
}
答案 0 :(得分:0)
您需要使用OutArgument并将它们用于变量。请参阅带有documentation的代码示例。
答案 1 :(得分:0)
使用内部变量在内部活动之间传递值。
虽然与您的代码没有直接关系,但请参阅下面的示例,它可以为您提供这个想法:
public sealed class CustomNativeActivity : NativeActivity<int>
{
private Variable<int> internalVar;
private Assign<int> internalAssign;
protected override void CacheMetadata(NativeActivityMetadata metadata)
{
base.CacheMetadata(metadata);
internalVar = new Variable<int>("intInternalVar", 10);
metadata.AddImplementationVariable(internalVar);
internalAssign = new Assign<int>
{
To = internalVar,
Value = 12345
};
metadata.AddImplementationChild(internalAssign);
}
protected override void Execute(NativeActivityContext context)
{
context.ScheduleActivity(internalAssign, (activityContext, instance) =>
{
// Use internalVar value, which was seted by previous activity
var value = internalVar.Get(activityContext);
Result.Set(activityContext, value);
});
}
}
调用上述活动:
WorkflowInvoker.Invoke<int>(new CustomNativeActivity());
将输出:
12345
修改强>
在您的情况下,您的 OutArgument 将是 internalVar
new OutArgument<int>(internalVar);
答案 2 :(得分:0)
我可能已经尝试过我想到的一切,但我很顽固,拒绝放弃,所以我继续思考;)
我在这里改变了我的例子,使用Data类作为参数(它本身不会改变任何东西,但我在现实世界的例子中需要它)。
下面的代码现在是一个关于如何访问传入数据的工作示例。使用实现变量是关键:
runtimeVariable = new Variable<Data>();
metadata.AddImplementationVariable(runtimeVariable);
OutArgument:
new OutArgument<Data>(runtimeVariable)
然后我可以通过以下方式访问该值:
// Here dataValue will get the incoming value.
var dataValue = runtimeVariable.Get(context);
我没有在其他地方看到过这样的例子。希望除了我以外,对任何人都有用。
代码:
[DataContract]
public class Data
{
[DataMember]
Guid Property1 { get; set; }
[DataMember]
int Property2 { get; set; }
}
public class TestActivity : NativeActivity<Guid>
{
public ReceiveContent Content { get; set; }
protected override void CacheMetadata(NativeActivityMetadata metadata)
{
runtimeVariable = new Variable<Data>();
metadata.AddImplementationVariable(runtimeVariable);
Content = ReceiveParametersContent.Create(new Dictionary<string, OutArgument>()
{
{"OutValue", new OutArgument<Data> (runtimeVariable)}
});
startReceiver = new Receive()
{
DisplayName = string.Format("Wait for workflow start request [Internal for {0}]", this.DisplayName),
CanCreateInstance = true,
ServiceContractName = XName.Get("IStartService", Namespace),
OperationName = "Start",
Content = Content
};
metadata.AddImplementationChild(startReceiver);
}
protected override void Execute(NativeActivityContext context)
{
context.ScheduleActivity(startReceiver, ReceiveDone);
}
private void ReceiveDone(NativeActivityContext context, ActivityInstance completedInstance)
{
// Here dataValue will get the incoming value.
var dataValue = runtimeVariable.Get(context);
}
private Receive startReceiver;
private Variable<Data> runtimeVariable;
private const string Namespace = "http://company.namespace";
}