簡體   English   中英

在自定義WF4活動中訪問Receive實現子活動的OutArgument值

[英]Accessing OutArgument value of Receive implementation child activity within custom WF4 activity

使用VS2012 / .NET 4.5,我正在創建一個自定義活動,該活動實現了Receive子活動(作為實現子項)。 在下面的示例中,參數僅固定為一個:Guid類型的OutValue。

我真的很想在ReceiveDone中訪問傳入參數的值,因為我需要使用它並對其進行轉換,然后再從活動返回它。 請忽略我當前正在使用Guid,它仍然無法通過和InvalidOperationException訪問值:

活動只能獲取其擁有的參數的位置。 活動“ 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";
}

您需要使用OutArgument及其變量。 請參閱文檔中的代碼示例。

使用內部變量在內部活動之間傳遞值。

盡管與您的代碼沒有直接關系,但請參見下面的示例,該示例應為您提供了思路:

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);

我可能已經嘗試了所有我想過的東西,但是我很固執,拒絕放棄,所以我一直在思考;)

我在這里更改了示例,改為使用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";
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM