0

使用 VS2012/.NET 4.5 我正在创建一个自定义活动,该活动实现了接收子活动(作为实现子活动)。以下示例中的参数仅固定为一个:Guid 类型的 OutValue。

我真的很想在 ReceiveDone 中访问传入参数值的值,因为我需要使用它并在从活动中返回它之前对其进行转换。请忽略我当前使用的是 Guid,它仍然无法使用 InvalidOperationException 访问该值:

Activity 只能获取它拥有的参数的位置。活动“TestActivity”正在尝试获取活动“等待工作流启动请求 [TestActivity 内部]”拥有的参数“OutValue”的位置

我已经尝试了我能想到的一切,但我惊呆了。一定有办法做这个非常简单的事情吗?

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";
}
4

3 回答 3

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);
于 2013-01-22T11:53:25.167 回答
0

您需要使用 OutArgument 并将它们用于变量。请参阅文档中的代码示例。

于 2013-01-22T11:26:48.493 回答
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";
}
于 2013-01-22T12:18:52.717 回答