2

MSDN でこの質問と同じ問題がありますが、単一のワークフロー インスタンスが同時に実行されているときに、Roman Kiss のソリューションがエンドポイント アドレスを正しく置き換えるかどうかがまだはっきりしないため、解決策がわかりません。

内部Sendアクティビティが特定のエンドポイント アドレスを持つ 1 つのスレッドによって実行されるようにスケジュールされている場合、このアドレスは、別のエンドポイント アドレスで同じアクティビティをスケジュールする別のスレッドによってオーバーライドされませんか? 間違っている場合は訂正してください。ただし、現在のワークフロー実行コンテキストが何であれ、バインドされSend.Endpointているのとは対照的に、通常のプロパティであるため、そうなると思います。InArgument<Endpoint>

誰かがこれにもっと光を当てることができますか?

アップデート

Roman Kiss が提供するソリューションをテストしたところ、私のシナリオでは期待どおりに機能しないことがわかりました。Executeメソッドを次のように変更しました。

protected override void Execute(NativeActivityContext context)
{
    Thread.Sleep(Address.Get(context).EndsWith("1") ? 1000 : 0);

    Body.Endpoint.Binding = GetBinding(Binding.Get(context));
    Body.Endpoint.AddressUri = new Uri(Address.Get(context));

    Thread.Sleep(Address.Get(context).EndsWith("1") ? 0 : 3000);
    var address = Address.Get(context) + " => " + Body.Endpoint.AddressUri;
    Console.WriteLine(address);
    Thread.Sleep(10000); 

    context.ScheduleActivity(Body);
}

このテストを実行しました:

static void Main(string[] args)
{
    // Workflow1 is just a SendScope wrapped around by a Sequence with single Address input argument exposed
    var workflow = new Workflow1();
    Task.WaitAll(
        Task.Run(() => WorkflowInvoker.Invoke(workflow, new Dictionary<string, object> { { "Address", @"http://localhost/1" } })),
        Task.Run(() => WorkflowInvoker.Invoke(workflow, new Dictionary<string, object> { { "Address", @"http://localhost/2" } })));

    Console.ReadLine();
}

私が得ている結果は次のとおりです。

http://localhost/1 => http://localhost/1

http://localhost/2 => http://localhost/1

質問は未解決のままです: 実行時にSendアクティビティのエンドポイント アドレスを動的に割り当てるにはどうすればよいですか?

4

1 に答える 1

1

新しい Sendアクティビティがファクトリによって作成されるため、CacheMetadataメソッドを使用してそのSendアクティビティをセットアップすると、アクティビティのそのインスタンスにバインディングが適切に設定されるため、これは示されているように機能します。

リンクダイのケースにコンテンツを含める

[ContentProperty("Body")]
public class SendScope : NativeActivity
{
    [DefaultValue((string)null)]
    [RequiredArgument]
    public InArgument<string> Binding { get; set; }

    [DefaultValue((string)null)]
    [RequiredArgument]
    public InArgument<string> Address { get; set; }

    [Browsable(false)]
    public Send Body { get; set; }

    protected override void CacheMetadata(NativeActivityMetadata metadata)
    {
        if (this.Body == null || this.Body.EndpointAddress != null)
        {
            metadata.AddValidationError("Error ...");
            return;
        }
        this.Body.Endpoint = new Endpoint()
        {
            AddressUri = new Uri("http://localhost/"),
            Binding = new BasicHttpBinding(),
            ServiceContractName = this.Body.ServiceContractName
        };
        metadata.AddChild(this.Body);
        base.CacheMetadata(metadata);
    }

    protected override void Execute(NativeActivityContext context)
    {
        this.Body.Endpoint.Binding = GetBinding(this.Binding.Get(context));
        this.Body.Endpoint.AddressUri = new Uri(this.Address.Get(context));
        context.ScheduleActivity(Body);
    }


    private System.ServiceModel.Channels.Binding GetBinding(string binding)
    {
        if (binding == "basicHttpBinding")
            return new BasicHttpBinding();
        //else ... others bindings
        return null;
    }
}

public class SendScopeFactory : IActivityTemplateFactory
{
    public Activity Create(DependencyObject target)
    {
        return new SendScope()
        {
            DisplayName = "SendScope",
            Body = new Send()
            {
                Action = "*",
                OperationName = "ProcessMessage",
                ServiceContractName = "IGenericContract",
            }
        };
    }
}
  1. Binding、Address、Security などのプロパティに基づいて、実行時に Send.Endpoint プロパティを設定するためのカスタム ネイティブ アクティビティを作成します。
  2. この SendScope アクティビティのデザイナーを CorrelationScope のようなものに作成します
  3. SendScopeFactory を作成します - 上記のコード スニペットを参照してください。
于 2012-09-12T11:37:23.907 に答える