Zugreifen auf OperationContext aus einem WorkflowdienstAccessing OperationContext from a Workflow Service

Für den Zugriff auf den OperationContext in einem Workflowdienst müssen Sie die IReceiveMessageCallback-Schnittstelle in einer benutzerdefinierten Ausführungseigenschaft implementieren.To access the OperationContext inside a workflow service, you must implement the IReceiveMessageCallback interface in a custom execution property. Überschreiben Sie die OnReceiveMessage(OperationContext, ExecutionProperties)-Methode, die als Verweis an den OperationContext übergeben wird.Override the OnReceiveMessage(OperationContext, ExecutionProperties) method which is passed a reference to the OperationContext. In diesem Thema erhalten Sie schrittweise Anweisungen zum Implementieren dieser Ausführungseigenschaft, um einen benutzerdefinierten Header sowie eine benutzerdefinierte Aktivität abzurufen, die diese Eigenschaft zur Laufzeit für Receive sichtbar macht.This topic will walk you through implementing this execution property to retrieve a custom header, as well as a custom activity that will surface this property to the Receive at runtime. Die benutzerdefinierte Aktivität implementiert dasselbe Verhalten wie eine System.ServiceModel.Activities.Sequence Aktivität, wenn jedoch eine Receive darin platziert wird, die IReceiveMessageCallback aufgerufen wird, und die OperationContext Informationen abgerufen werden soll.The custom activity will implement the same behavior as a System.ServiceModel.Activities.Sequence activity, except that when a Receive is placed inside of it, the IReceiveMessageCallback will be called and the OperationContext information will be retrieved. In diesem Thema wird zudem veranschaulicht, wie auf den clientseitigen OperationContext zugegriffen wird, um über die ISendMessageCallback-Schnittstelle ausgehende Header hinzuzufügen.This topic also shows how to access the client-side OperationContext to add outgoing headers via the ISendMessageCallback interface.

Implementieren des dienstseitigen IReceiveMessageCallbackImplement the Service-side IReceiveMessageCallback

  1. Erstellen Sie eine leere Visual Studio 2012Visual Studio 2012-Projektmappe.Create an empty Visual Studio 2012Visual Studio 2012 solution.

  2. Fügen Sie der Projektmappe eine neue Konsolenanwendung mit dem Namen Service hinzu.Add a new console application called Service to the solution.

  3. Fügen Sie Verweise auf die folgenden Assemblys hinzu:Add references to the following assemblies:

    1. System.Runtime.SerializationSystem.Runtime.Serialization

    2. System.ServiceModelSystem.ServiceModel

    3. System.ServiceModel.ActivitiesSystem.ServiceModel.Activities

  4. Fügen Sie eine neue Klasse mit dem Namen ReceiveInstanceIdCallback hinzu, und implementieren Sie IReceiveMessageCallback, wie im folgenden Beispiel veranschaulicht.Add a new class called ReceiveInstanceIdCallback and implement IReceiveMessageCallback as shown in the following example.

    class ReceiveInstanceIdCallback : IReceiveMessageCallback  
    {  
          public const string HeaderName = "InstanceIdHeader";  
          public const string HeaderNS = "http://Microsoft.Samples.AccessingOperationContext";  
    
         public void OnReceiveMessage(System.ServiceModel.OperationContext operationContext, System.Activities.ExecutionProperties activityExecutionProperties)  
          {              
                try  
                {  
                    Guid instanceId = operationContext.IncomingMessageHeaders.GetHeader<Guid>(HeaderName, HeaderNS);  
                    Console.WriteLine("Received a message from a workflow with instanceId = {0}", instanceId);  
                }  
                catch (MessageHeaderException)  
                {  
                    Console.WriteLine("This message must not be from a workflow.");  
                }  
            }  
    }  
    

    In diesem Code wird mit dem an die Methode übergebenen OperationContext auf die Header der eingehenden Nachricht zugegriffen.This code uses the OperationContext passed into the method to access the incoming message’s headers.

Implementieren einer dienstseitigen systemeigenen Aktivität, um dem NativeActivityContext die IReceiveMessageCallback-Implementierung hinzuzufügenImplement a Service-side Native activity to add the IReceiveMessageCallback implementation to the NativeActivityContext

  1. Fügen Sie eine neue, von NativeActivity abgeleitete Klasse mit dem Namen ReceiveInstanceIdScope hinzu.Add a new class derived from NativeActivity called ReceiveInstanceIdScope.

  2. Fügen Sie lokale Variablen hinzu, um untergeordnete Aktivitäten, Variablen, den aktuellen Aktivitätsindex und einen CompletionCallback-Rückruf zu verfolgen.Add local variables to keep track of child activities, variables, current activity index, and a CompletionCallback callback.

    public sealed class ReceiveInstanceIdScope : NativeActivity  
        {  
            Collection<Activity> children;  
            Collection<Variable> variables;  
            Variable<int> currentIndex;  
            CompletionCallback onChildComplete;  
    }  
    
  3. Implementieren des KonstruktorsImplement the constructor

    public ReceiveInstanceIdScope()  
                : base()  
            {  
                this.children = new Collection<Activity>();  
                this.variables = new Collection<Variable>();  
                this.currentIndex = new Variable<int>();  
            }  
    }  
    
  4. Implementieren Sie die Activities-Eigenschaft und die Variables-Eigenschaft.Implement the Activities and Variables properties.

    public Collection<Activity> Activities  
    {  
         get { return this.children; }  
    }  
    
    public Collection<Variable> Variables  
    {  
        get { return this.variables; }  
    }  
    
  5. Überschreiben Sie CacheMetadata.Override CacheMetadata

    protected override void CacheMetadata(NativeActivityMetadata metadata)  
    {  
        //call base.CacheMetadata to add the Activities and Variables to this activity's metadata  
        base.CacheMetadata(metadata);  
        //add the private implementation variable: currentIndex   
        metadata.AddImplementationVariable(this.currentIndex);  
    }  
    
  6. Überschreiben Sie Execute.Override Execute

    protected override void Execute(  
                NativeActivityContext context)  
            {  
                context.Properties.Add("ReceiveInstanceIdCallback", new ReceiveInstanceIdCallback());  
                InternalExecute(context, null);  
            }  
    
            void InternalExecute(NativeActivityContext context, ActivityInstance instance)  
            {  
                //grab the index of the current Activity  
                int currentActivityIndex = this.currentIndex.Get(context);  
                if (currentActivityIndex == Activities.Count)  
                {  
                    //if the currentActivityIndex is equal to the count of MySequence's Activities  
                    //MySequence is complete  
                    return;  
                }  
    
                if (this.onChildComplete == null)  
                {  
                    //on completion of the current child, have the runtime call back on this method  
                    this.onChildComplete = new CompletionCallback(InternalExecute);  
                }  
    
                //grab the next Activity in MySequence.Activities and schedule it  
                Activity nextChild = Activities[currentActivityIndex];  
                context.ScheduleActivity(nextChild, this.onChildComplete);  
    
                //increment the currentIndex  
                this.currentIndex.Set(context, ++currentActivityIndex);  
            }  
    

Implementieren des WorkflowdienstsImplement the workflow service

  1. Öffnen Sie die vorhandene Program Klasse.Open the existing Program class.

  2. Definieren Sie die folgenden Konstanten:Define the following constants:

    class Program  
    {  
       const string addr = "http://localhost:8080/Service";  
       static XName contract = XName.Get("IService", "http://tempuri.org");  
    }  
    
  3. Fügen Sie eine statische Methode mit dem Namen GetWorkflowService hinzu, die den Workflowdienst erstellt.Add a static method called GetWorkflowService that creates the workflow service.

    static Activity GetServiceWorkflow()  
            {  
                Variable<string> echoString = new Variable<string>();  
    
                Receive echoRequest = new Receive  
                {  
                    CanCreateInstance = true,  
                    ServiceContractName = contract,  
                    OperationName = "Echo",  
                    Content = new ReceiveParametersContent()  
                    {  
                        Parameters = { { "echoString", new OutArgument<string>(echoString) } }  
                    }  
                };  
    
                return new ReceiveInstanceIdScope  
                {  
                    Variables = { echoString },  
                    Activities =  
                    {  
                        echoRequest,  
                        new WriteLine { Text = new InArgument<string>( (e) => "Received: " + echoString.Get(e) ) },  
                        new SendReply  
                        {  
                            Request = echoRequest,  
                            Content = new SendParametersContent()  
                            {  
                                Parameters = { { "result", new InArgument<string>(echoString) } }   
                            }  
                        }  
                    }  
                };  
            }  
    
  4. Hosten Sie den Workflowdienst in der vorhandenen Main-Methode.In the existing Main method, host the workflow service.

    static void Main(string[] args)  
            {  
                string addr = "http://localhost:8080/Service";  
    
                using (WorkflowServiceHost host = new WorkflowServiceHost(GetServiceWorkflow()))  
                {  
                    host.AddServiceEndpoint(contract, new BasicHttpBinding(), addr);  
    
                    host.Open();  
                    Console.WriteLine("Service waiting at: " + addr);  
                    Console.WriteLine("Press [ENTER] to exit");  
                    Console.ReadLine();  
                    host.Close();  
                }  
            }  
    

Implementieren des clientseitigen ISendMessageCallbackImplement the Client-side ISendMessageCallback

  1. Fügen Sie der Projektmappe eine neue Konsolenanwendung mit dem Namen Service hinzu.Add a new console application called Service to the solution.

  2. Fügen Sie Verweise auf die folgenden Assemblys hinzu:Add references to the following assemblies:

    1. System.Runtime.SerializationSystem.Runtime.Serialization

    2. System.ServiceModelSystem.ServiceModel

    3. System.ServiceModel.ActivitiesSystem.ServiceModel.Activities

  3. Fügen Sie eine neue Klasse mit dem Namen SendInstanceIdCallback hinzu, und implementieren Sie ISendMessageCallback, wie im folgenden Beispiel veranschaulicht.Add a new class called SendInstanceIdCallback and implement ISendMessageCallback as shown in the following example.

    class SendInstanceIdCallback : ISendMessageCallback  
        {  
            public const string HeaderName = "InstanceIdHeader";  
            public const string HeaderNS = "http://Microsoft.Samples.AccessingOperationContext";  
    
            public Guid InstanceId { get; set; }  
    
            public void OnSendMessage(System.ServiceModel.OperationContext operationContext)  
            {  
                operationContext.OutgoingMessageHeaders.Add(MessageHeader.CreateHeader(HeaderName, HeaderNS, this.InstanceId));  
            }  
        }  
    

    In diesem Code wird mit dem an die Methode übergebenen OperationContext der eingehenden Nachricht ein benutzerdefinierter Header hinzugefügt.This code uses the OperationContext passed into the method to add a custom header to the incoming message.

Implementieren einer clientseitigen systemeigenen Aktivität, um dem NativeActivityContext die clientseitige ISendMessageCallback-Implementierung hinzuzufügenImplement a Client-side Native activity to add the client-side ISendMessageCallback implementation to the NativeActivityContext

  1. Fügen Sie eine neue, von NativeActivity abgeleitete Klasse mit dem Namen SendInstanceIdScope hinzu.Add a new class derived from NativeActivity called SendInstanceIdScope.

  2. Fügen Sie lokale Variablen hinzu, um untergeordnete Aktivitäten, Variablen, den aktuellen Aktivitätsindex und einen CompletionCallback-Rückruf zu verfolgen.Add local variables to keep track of child activities, variables, current activity index, and a CompletionCallback callback.

    public sealed class SendInstanceIdScope : NativeActivity  
        {  
            Collection<Activity> children;  
            Collection<Variable> variables;  
            Variable<int> currentIndex;  
            CompletionCallback onChildComplete;  
    }  
    
  3. Implementieren des KonstruktorsImplement the constructor

    public SendInstanceIdScope()  
                : base()  
            {  
                this.children = new Collection<Activity>();  
                this.variables = new Collection<Variable>();  
                this.currentIndex = new Variable<int>();  
            }  
    
  4. Implementieren Sie die Activities-Eigenschaft und die Variables-Eigenschaft.Implement the Activities and Variables properties.

    public Collection<Activity> Activities  
    {  
         get { return this.children; }  
    }  
    
    public Collection<Variable> Variables  
    {  
        get { return this.variables; }  
    }  
    
  5. Überschreiben Sie CacheMetadata.Override CacheMetadata

    protected override void CacheMetadata(NativeActivityMetadata metadata)  
    {  
        //call base.CacheMetadata to add the Activities and Variables to this activity's metadata  
        base.CacheMetadata(metadata);  
        //add the private implementation variable: currentIndex   
        metadata.AddImplementationVariable(this.currentIndex);  
    }  
    
  6. Überschreiben Sie Execute.Override Execute

    protected override void Execute(  
                NativeActivityContext context)  
            {  
                context.Properties.Add("SendInstanceIdCallback", new SendInstanceIdCallback() { InstanceId = context.WorkflowInstanceId });  
                InternalExecute(context, null);  
            }  
    
            void InternalExecute(NativeActivityContext context, ActivityInstance instance)  
            {  
                //grab the index of the current Activity  
                int currentActivityIndex = this.currentIndex.Get(context);  
                if (currentActivityIndex == Activities.Count)  
                {  
                    //if the currentActivityIndex is equal to the count of MySequence's Activities  
                    //MySequence is complete  
                    return;  
                }  
    
                if (this.onChildComplete == null)  
                {  
                    //on completion of the current child, have the runtime call back on this method  
                    this.onChildComplete = new CompletionCallback(InternalExecute);  
                }  
    
                //grab the next Activity in MySequence.Activities and schedule it  
                Activity nextChild = Activities[currentActivityIndex];  
                context.ScheduleActivity(nextChild, this.onChildComplete);  
    
                //increment the currentIndex  
                this.currentIndex.Set(context, ++currentActivityIndex);  
            }  
    protected override void Execute(  
                NativeActivityContext context)  
            {  
                context.Properties.Add("ReceiveInstanceIdCallback", new ReceiveInstanceIdCallback());  
                InternalExecute(context, null);  
            }  
    
            void InternalExecute(NativeActivityContext context, ActivityInstance instance)  
            {  
                //grab the index of the current Activity  
                int currentActivityIndex = this.currentIndex.Get(context);  
                if (currentActivityIndex == Activities.Count)  
                {  
                    //if the currentActivityIndex is equal to the count of MySequence's Activities  
                    //MySequence is complete  
                    return;  
                }  
    
                if (this.onChildComplete == null)  
                {  
                    //on completion of the current child, have the runtime call back on this method  
                    this.onChildComplete = new CompletionCallback(InternalExecute);  
                }  
    
                //grab the next Activity in MySequence.Activities and schedule it  
                Activity nextChild = Activities[currentActivityIndex];  
                context.ScheduleActivity(nextChild, this.onChildComplete);  
    
                //increment the currentIndex  
                this.currentIndex.Set(context, ++currentActivityIndex);  
            }  
    

Implementieren eines WorkflowclientsImplement a workflow client

  1. Erstellen Sie ein neues Konsolenanwendungsprojekt mit dem Namen Client.Create a new console application project called Client.

  2. Fügen Sie Verweise auf die folgenden Assemblys hinzu:Add references to the following assemblies:

    1. System.ActivitiesSystem.Activities

    2. System.ServiceModelSystem.ServiceModel

    3. System.ServiceModel.ActivitiesSystem.ServiceModel.Activities

  3. Öffnen Sie die generierte Datei Program.cs, und fügen Sie eine statische Methode mit dem Namen GetClientWorkflow hinzu, um den Clientworkflow zu erstellen.Open the generated Program.cs file and add a static method called GetClientWorkflow to create the client workflow.

    static Activity GetClientWorkflow()  
            {  
                Variable<string> echoString = new Variable<string>();  
    
                // Define the endpoint  
                Endpoint clientEndpoint = new Endpoint  
                {  
                    Binding = new BasicHttpBinding(),  
                    AddressUri = new Uri("http://localhost:8080/Service")  
                };  
    
                // Configure the Send activity used to send a message  
                Send echoRequest = new Send  
                {  
                    Endpoint = clientEndpoint,  
                    ServiceContractName = XName.Get("IService", "http://tempuri.org"),  
                    OperationName = "Echo",  
                    Content = new SendParametersContent()  
                    {  
                        Parameters = { { "echoString", new InArgument<string>("Hello, World") } }   
                    }  
                };  
    
                // Place the Send activity in a SendInstanceIdScope. This hooks up the ISendMessageCallback   
                // implementation to the client workflow.  
                return new SendInstanceIdScope  
                {  
                    Variables = { echoString },  
                    Activities =  
                    {                      
                        new CorrelationScope  
                        {  
                            Body = new Sequence  
                            {  
                                Activities =   
                                {  
                                    // Send the request message  
                                    echoRequest,  
    
                                   // Receive the reply from the service  
                                    new ReceiveReply  
                                    {  
                                        Request = echoRequest,  
                                        Content = new ReceiveParametersContent  
                                        {  
                                            Parameters = { { "result", new OutArgument<string>(echoString) } }  
                                        }  
                                    }  
                                }  
                            }  
                        },                      
                        new WriteLine { Text = new InArgument<string>( (e) => "Received Text: " + echoString.Get(e) ) },                      
                    }  
                };  
            }  
    
  4. Fügen Sie der Main()-Methode den folgenden Hostcode hinzu.Add the following hosting code to the Main() method.

    static void Main(string[] args)  
    {  
       Activity workflow = GetClientWorkflow();  
       WorkflowInvoker.Invoke(workflow);  
       WorkflowInvoker.Invoke(workflow);  
       Console.WriteLine("Press [ENTER] to exit");  
       Console.ReadLine();  
    }  
    

BeispielExample

Im Folgenden finden Sie eine vollständige Auflistung des in diesem Thema verwendeten Quellcodes.Here is a complete listing of the source code used in this topic.

// ReceiveInstanceIdScope.cs  
//----------------------------------------------------------------  
// Copyright (c) Microsoft Corporation.  All rights reserved.  
//----------------------------------------------------------------  

using System.Activities;  
using System.Collections.ObjectModel;  

namespace Microsoft.Samples.AccessingOperationContext.Service  
{  
    public sealed class ReceiveInstanceIdScope : NativeActivity  
    {  
        Collection<Activity> children;  
        Collection<Variable> variables;  
        Variable<int> currentIndex;  
        CompletionCallback onChildComplete;  

        public ReceiveInstanceIdScope()  
            : base()  
        {  
            this.children = new Collection<Activity>();  
            this.variables = new Collection<Variable>();  
            this.currentIndex = new Variable<int>();  
        }  

        public Collection<Activity> Activities  
        {  
            get  
            {  
                return this.children;  
            }  
        }  

        public Collection<Variable> Variables  
        {  
            get  
            {  
                return this.variables;  
            }  
        }  

        protected override void CacheMetadata(NativeActivityMetadata metadata)  
        {  
            //call base.CacheMetadata to add the Activities and Variables to this activity's metadata  
            base.CacheMetadata(metadata);  
            //add the private implementation variable: currentIndex   
            metadata.AddImplementationVariable(this.currentIndex);  
        }                     

        protected override void Execute(  
            NativeActivityContext context)  
        {  
            context.Properties.Add("ReceiveInstanceIdCallback", new ReceiveInstanceIdCallback());  
            InternalExecute(context, null);  
        }  

        void InternalExecute(NativeActivityContext context, ActivityInstance instance)  
        {  
            //grab the index of the current Activity  
            int currentActivityIndex = this.currentIndex.Get(context);  
            if (currentActivityIndex == Activities.Count)  
            {  
                //if the currentActivityIndex is equal to the count of MySequence's Activities  
                //MySequence is complete  
                return;  
            }  

            if (this.onChildComplete == null)  
            {  
                //on completion of the current child, have the runtime call back on this method  
                this.onChildComplete = new CompletionCallback(InternalExecute);  
            }  

            //grab the next Activity in MySequence.Activities and schedule it  
            Activity nextChild = Activities[currentActivityIndex];  
            context.ScheduleActivity(nextChild, this.onChildComplete);  

            //increment the currentIndex  
            this.currentIndex.Set(context, ++currentActivityIndex);  
        }  
    }  
}  
// ReceiveInstanceIdScope.cs  
//----------------------------------------------------------------  
// Copyright (c) Microsoft Corporation.  All rights reserved.  
//----------------------------------------------------------------  

using System;  
using System.ServiceModel;  
using System.ServiceModel.Activities;  

namespace Microsoft.Samples.AccessingOperationContext.Service  
{  
    class ReceiveInstanceIdCallback : IReceiveMessageCallback  
    {  
        public const string HeaderName = "InstanceIdHeader";  
        public const string HeaderNS = "http://Microsoft.Samples.AccessingOperationContext";  

        public void OnReceiveMessage(System.ServiceModel.OperationContext operationContext, System.Activities.ExecutionProperties activityExecutionProperties)  
        {              
            try  
            {  
                Guid instanceId = operationContext.IncomingMessageHeaders.GetHeader<Guid>(HeaderName, HeaderNS);  
                Console.WriteLine("Received a message from a workflow with instanceId = {0}", instanceId);  
            }  
            catch (MessageHeaderException)  
            {  
                Console.WriteLine("This message must not be from a workflow.");  
            }  
        }  
    }  
}  
// Service.cs  
//----------------------------------------------------------------  
// Copyright (c) Microsoft Corporation.  All rights reserved.  
//----------------------------------------------------------------  

using System;  
using System.Activities;  
using System.Activities.Statements;  
using System.ServiceModel;  
using System.ServiceModel.Activities;  
using System.Xml.Linq;  

namespace Microsoft.Samples.AccessingOperationContext.Service  
{      
    class Program  
    {  
        const string addr = "http://localhost:8080/Service";  
        static XName contract = XName.Get("IService", "http://tempuri.org");  

        static void Main(string[] args)  
        {  
            string addr = "http://localhost:8080/Service";  

            using (WorkflowServiceHost host = new WorkflowServiceHost(GetServiceWorkflow()))  
            {  
                host.AddServiceEndpoint(contract, new BasicHttpBinding(), addr);  

                host.Open();  
                Console.WriteLine("Service waiting at: " + addr);  
                Console.WriteLine("Press [ENTER] to exit");  
                Console.ReadLine();  
                host.Close();  
            }  

        }  

        static Activity GetServiceWorkflow()  
        {  
            Variable<string> echoString = new Variable<string>();  

            Receive echoRequest = new Receive  
            {  
                CanCreateInstance = true,  
                ServiceContractName = contract,  
                OperationName = "Echo",  
                Content = new ReceiveParametersContent()  
                {  
                    Parameters = { { "echoString", new OutArgument<string>(echoString) } }  
                }  
            };  

            return new ReceiveInstanceIdScope  
            {  
                Variables = { echoString },  
                Activities =  
                {  
                    echoRequest,  
                    new WriteLine { Text = new InArgument<string>( (e) => "Received: " + echoString.Get(e) ) },  
                    new SendReply  
                    {  
                        Request = echoRequest,  
                        Content = new SendParametersContent()  
                        {  
                            Parameters = { { "result", new InArgument<string>(echoString) } }   
                        }  
                    }  
                }  
            };  
        }  
    }  

}  
// SendInstanceIdCallback.cs  
//----------------------------------------------------------------  
// Copyright (c) Microsoft Corporation.  All rights reserved.  
//----------------------------------------------------------------  

using System;  
using System.ServiceModel.Activities;  
using System.ServiceModel.Channels;  

namespace Microsoft.Samples.AccessingOperationContext.Client  
{  
    class SendInstanceIdCallback : ISendMessageCallback  
    {  
        public const string HeaderName = "InstanceIdHeader";  
        public const string HeaderNS = "http://Microsoft.Samples.AccessingOperationContext";  

        public Guid InstanceId { get; set; }  

        public void OnSendMessage(System.ServiceModel.OperationContext operationContext)  
        {  
            operationContext.OutgoingMessageHeaders.Add(MessageHeader.CreateHeader(HeaderName, HeaderNS, this.InstanceId));  
        }  
    }  
}  
// SendInstanceIdScope.cs  
//----------------------------------------------------------------  
// Copyright (c) Microsoft Corporation.  All rights reserved.  
//----------------------------------------------------------------  

using System.Activities;  
using System.Collections.ObjectModel;  

namespace Microsoft.Samples.AccessingOperationContext.Client  
{  
    public sealed class SendInstanceIdScope : NativeActivity  
    {  
        Collection<Activity> children;  
        Collection<Variable> variables;  
        Variable<int> currentIndex;  
        CompletionCallback onChildComplete;  

        public SendInstanceIdScope()  
            : base()  
        {  
            this.children = new Collection<Activity>();  
            this.variables = new Collection<Variable>();  
            this.currentIndex = new Variable<int>();  
        }  

        public Collection<Activity> Activities  
        {  
            get  
            {  
                return this.children;  
            }  
        }  

        public Collection<Variable> Variables  
        {  
            get  
            {  
                return this.variables;  
            }  
        }  

        protected override void CacheMetadata(NativeActivityMetadata metadata)  
        {  
            //call base.CacheMetadata to add the Activities and Variables to this activity's metadata  
            base.CacheMetadata(metadata);  
            //add the private implementation variable: currentIndex   
            metadata.AddImplementationVariable(this.currentIndex);  
        }  

        protected override void Execute(  
            NativeActivityContext context)  
        {  
            context.Properties.Add("SendInstanceIdCallback", new SendInstanceIdCallback() { InstanceId = context.WorkflowInstanceId });  
            InternalExecute(context, null);  
        }  

        void InternalExecute(NativeActivityContext context, ActivityInstance instance)  
        {  
            //grab the index of the current Activity  
            int currentActivityIndex = this.currentIndex.Get(context);  
            if (currentActivityIndex == Activities.Count)  
            {  
                //if the currentActivityIndex is equal to the count of MySequence's Activities  
                //MySequence is complete  
                return;  
            }  

            if (this.onChildComplete == null)  
            {  
                //on completion of the current child, have the runtime call back on this method  
                this.onChildComplete = new CompletionCallback(InternalExecute);  
            }  

            //grab the next Activity in MySequence.Activities and schedule it  
            Activity nextChild = Activities[currentActivityIndex];  
            context.ScheduleActivity(nextChild, this.onChildComplete);  

            //increment the currentIndex  
            this.currentIndex.Set(context, ++currentActivityIndex);  
        }  
    }  
}  
// Client.cs  
//----------------------------------------------------------------  
// Copyright (c) Microsoft Corporation.  All rights reserved.  
//----------------------------------------------------------------  

using System;  
using System.Activities;  
using System.Activities.Statements;  
using System.ServiceModel;  
using System.ServiceModel.Activities;  
using System.Xml.Linq;  

namespace Microsoft.Samples.AccessingOperationContext.Client  
{  
    class Program  
    {  
        static void Main(string[] args)  
        {  
            Activity workflow = GetClientWorkflow();  
            WorkflowInvoker.Invoke(workflow);  
            WorkflowInvoker.Invoke(workflow);  
            Console.WriteLine("Press [ENTER] to exit");  
            Console.ReadLine();  
        }  

        static Activity GetClientWorkflow()  
        {  
            Variable<string> echoString = new Variable<string>();  

            Endpoint clientEndpoint = new Endpoint  
            {  
                Binding = new BasicHttpBinding(),  
                AddressUri = new Uri("http://localhost:8080/Service")  
            };  

            Send echoRequest = new Send  
            {  
                Endpoint = clientEndpoint,  
                ServiceContractName = XName.Get("IService", "http://tempuri.org"),  
                OperationName = "Echo",  
                Content = new SendParametersContent()  
                {  
                    Parameters = { { "echoString", new InArgument<string>("Hello, World") } }   
                }  
            };  

            return new SendInstanceIdScope  
            {  
                Variables = { echoString },  
                Activities =  
                {                      
                    new CorrelationScope  
                    {  
                        Body = new Sequence  
                        {  
                            Activities =   
                            {  
                                echoRequest,  
                                new ReceiveReply  
                                {  
                                    Request = echoRequest,  
                                    Content = new ReceiveParametersContent  
                                    {  
                                        Parameters = { { "result", new OutArgument<string>(echoString) } }  
                                    }  
                                }  
                            }  
                        }  
                    },                      
                    new WriteLine { Text = new InArgument<string>( (e) => "Received Text: " + echoString.Get(e) ) },                      
                }  
            };  
        }  
    }  
}  

Optionale Kommentare.Optional comments.

Siehe auchSee Also

WorkflowdiensteWorkflow Services
Zugreifen auf OperationContextAccessing OperationContext
Erstellen von Workflows, Aktivitäten und Ausdrücken mit imperativem CodeAuthoring Workflows, Activities, and Expressions Using Imperative Code