Sie sind auf Seite 1von 32

Visual Studio® 2008:

Windows® Workflow
Foundation
Module 4: Creating and Configuring Custom
Activities
• Creating Custom Activities

• Creating Custom Composite Activities

• Customizing Activity Serialization

• Defining Custom Activity Layout


Lesson: Creating Custom Activities
• Overview of Custom Activities

• Creating a Custom Activity

• Defining Instance Properties and Meta Properties

• Defining Dependency Properties

• Implementing Execution Logic

• Raising Events

• Defining Activity Validators

• Demonstration: Creating Custom Activities


Overview of Custom Activities
Simple custom activities:
• Encapsulate recurring
workflow functionality

Custom composite activities:


• Wrap a collection of related
activities into a reusable
high-level activity
Creating a Custom Activity
To create a custom activity:
• Create a Windows Activity Library project
• Define a class that inherits from Activity or a derived type
• Annotate the activity with attributes

[ToolboxBitmap(typeof(SendEmailActivity), "EmailMessage.png")]
public partial class SendEmailActivity : Activity
{

}
Defining Instance Properties and Meta Properties
Instance properties:
• Can be set at design time or can be bound to instance data
• Can be modified directly during workflow execution

Meta properties:
• Must be set to a literal value at design time
• Cannot be modified during workflow execution

private string toAddress;

[Browsable(true)]
public string ToAddress
{
get { return toAddress; }
set { toAddress = value; }
}
Defining Dependency Properties
What are dependency properties?
• A centralized repository of the state of a workflow
• Can be bound to other values on the workflow

public static DependencyProperty FromAddressProperty =


DependencyProperty.Register(
"FromAddress",
typeof(String),
typeof(SendEmailActivity),
new PropertyMetadata("admin@contoso.com"));

public string FromAddress


{
get { return (String)(base.GetValue(FromAddressProperty)); }
set { base.SetValue(FromAddressProperty, value); }
}
Implementing Execution Logic
To implement the execution logic for a custom activity:
• Override the Execute method
• Implement your custom logic
• Return an ActivityExecutionStatus value

protected override ActivityExecutionStatus Execute(


ActivityExecutionContext context)
{
// Implement execution logic here.

return ActivityExecutionStatus.Closed;
}
Raising Events
Define a custom EventArgs class, if appropriate

public class CustomActivityEventArgs : EventArgs


{

}

In the custom activity class:


• Declare the event as a dependency property
• Raise the event in the custom logic for the activity

public static DependencyProperty AnEvent = … ;



CustomActivityEventArgs args = new CustomActivityEventArgs(…);
base.RaiseGenericEvent<CustomActivityEventArgs>(AnEvent, this, args);
Defining Activity Validators
You can define a class to validate an activity
• Define a class that inherits from ActivityValidator
• Implement functionality to validate properties

public class SendEmailValidator : ActivityValidator


{

}

To associate an activity with an activity validator class:


• Annotate the activity class with the ActivityValidator attribute

[ActivityValidator(typeof(SendEmailValidator))]
public partial class SendEmailActivity : Activity
{

}
Demonstration: Creating Custom Activities
In this demonstration, you will see how to:
• Create a custom activity

• Define a validator for a custom activity

• Use the custom activity in a workflow


Lesson: Creating Custom Composite Activities
• Creating a Custom Composite Activity

• Adding Child Activities to a Custom Composite Activity

• Creating a Sequential Custom Composite Activity

• Adding Child Activities to a Sequential Custom Composite


Activity
• Demonstration: Creating Custom Composite Activities
Creating a Custom Composite Activity
To create a custom composite activity:
• Define a class that inherits from CompositeActivity
• Annotate the activity with attributes
• Define properties to hold state for the activity

[ToolboxBitmap(typeof(MyCompositeActivity), "MyBitmap.png")]
public class MyCompositeActivity : CompositeActivity
{
// Properties

}
Adding Child Activities to a Custom Composite
Activity
To add child activities to a custom composite activity:
• Implement InitializeComponent, to add child activities
• Override Execute, to handle the execution of child activities

[ToolboxBitmap(typeof(MyCompositeActivity), "MyBitmap.png")]
public class MyCompositeActivity : CompositeActivity
{
private void InitializeComponent()
{ … }

protected override ActivityExecutionStatus Execute(


ActivityExecutionContext ctx)
{ … }
}

You must manage the completion of the composite activity


• Implement logic to close the composite activity when appropriate
Creating a Sequential Custom Composite Activity
To create a sequential custom composite activity:
• Define a class that inherits from SequenceActivity
• Annotate the class with attributes
• Define properties to hold state for the activity

[ToolboxBitmap(typeof(MessageBoxActivity), "MessageBoxBitmap.png")]
public class MessageBoxActivity : SequenceActivity
{
// Properties

}
Adding Child Activities to a Sequential Custom
Composite Activity
To add child activities to a sequential custom composite
activity:
• Drag activities from the Toolbox and drop them onto the Designer
surface

The Designer manages the


layout of child activities

• Same as for a normal


SequenceActivity
Demonstration: Creating Custom Composite
Activities
In this demonstration, you will see how to:
• Create a custom composite activity

• Add child activities to the custom composite activity

• Use the custom composite activity in a workflow


Lesson: Customizing Activity Serialization
• Default Serialization Infrastructure

• Serializing and Deserializing Workflows

• Demonstration: Serializing and Deserializing Workflows

• Custom Serialization

• Defining a Custom Serializer

• Associating a Custom Serializer with a Custom Activity


Default Serialization Infrastructure
The default serialization infrastructure provides all the
types required to serialize most workflows and activities

Provides basic
WorkflowMarkupSerializer
serialization services

ActivityMarkupSerializer CompositeActivityMarkupSerializer

Serializes basic activities Serializes composite activities


Serializing and Deserializing Workflows
To serialize a workflow:
• Create an XmlWriter object
• Create a WorkflowMarkupSerializer object
• Invoke the Serialize method on the WorkflowMarkupSerializer

To deserialize a workflow:
• Create an XmlReader object to read the serialized workflow file
• Create a WorkflowRuntime object
• Invoke the CreateWorkflow method on the WorkflowRuntime
Demonstration: Serializing and Deserializing
Workflows
In this demonstration, you will see how to:
• Serialize a workflow to XAML

• Deserialize a workflow from XAML


Custom Serialization
Custom activity classes implicitly support the default
serialization behavior
• Sufficient for most custom activity classes

However, there
• TODO: Show anare specific
example of ascenarios where
deployment the file?
manifest default
serialization might be inadequate for a custom activity
• In this case, you must define a custom serializer class for the
custom activity class
• You must associate the custom serializer class with the custom
activity class
Defining a Custom Serializer
To define a custom serializer:
• Define a class that inherits from WorkflowMarkupSerializer
• Override serialization and deserialization methods

public class MyMarkupSerializer : WorkflowMarkupSerializer


{
protected override void OnBeforeSerialize(…) { … }

protected override void OnAfterSerialize(…) { … }

protected override void OnBeforeDeserialize(…) { … }

protected override void OnAfterDeserialize(…) { … }


}
Associating a Custom Serializer with a Custom
Activity
To associate a custom serializer with a custom activity:
• Annotate the custom activity class with the DesignerSerializer
attribute
• Specify the type and base type of the custom serializer

[DesignerSerializer(typeof(MyMarkupSerializer,
typeof(WorkflowMarkupSerializer))]
public class MyActivity : Activity
{

}
Lesson: Defining Custom Activity Layout
• Default Designers

• Defining a Custom Designer for a Custom Activity

• Specifying the Designer for a Custom Activity

• Specifying the Designer for a Custom Composite Activity


Default Designers
Windows Workflow Foundation provides several designer
classes to render workflow activities in the designer

ActivityDesigner

CompositeActivityDesigner

FreeformActivityDesigner StructuredCompositeActivityDesigner

ParallelActivityDesigner SequentialActivityDesigner
Defining a Custom Designer for a Custom Activity
To create a custom designer for a custom activity:
• Define a class that inherits from an existing designer class
• Override members from the base designer class
• Associate a theme class with the designer class, if appropriate

[ActivityDesignerTheme(typeof(MyTheme))]
public class MyActivityDesigner : ActivityDesigner
{
protected override Rectangle ImageRectangle
{ … }

protected override Rectangle TextRectangle


{ … }

protected override void Initialize(Activity a)


{ … }

protected override void OnPaint(ActivityDesignerPaintEventArgs e)


{ … }
}
Specifying the Designer for a Custom Activity
To specify the designer for a custom activity:
• Annotate the activity class with the Designer attribute

[Designer(typeof(MyActivityDesigner))]
public class MyActivity : Activity
{

}
Specifying the Designer for a Custom Composite
Activity
To specify the designer for a custom composite activity:
• Set the Designer attribute to SequentialActivityDesigner or
ParallelActivityDesigner

[Designer(typeof(SequentialActivityDesigner))]
public class CompositeActivity1 : CompositeActivity …
{

}

[Designer(typeof(ParallelActivityDesigner))]
public class CompositeActivity2 : CompositeActivity
{

}
Lab: Creating and Configuring Custom Activities
• Exercise 1: Creating a Custom Activity

• Exercise 2: Validating a Custom Activity

• Exercise 3: Developing a Custom Activity Designer


(If Time Permits)
• Exercise 4: Creating a Custom Composite Activity
(If Time Permits)

Logon information

Virtual machine 6462A-LON-DEV-04

User name Student

Password Pa$$w0rd

Estimated time: 60 minutes


Lab Review
• What is the purpose of defining a validator for
SendEmailActivity? Why is there no need to define a
validator for MessageBoxActivity?
• What is the purpose of defining a designer for
SendEmailActivity? Why is there no need to define a
designer for MessageBoxActivity?
Module Review and Takeaways
• Review Questions

• Real-World Issues and Scenarios

• Best Practices

Das könnte Ihnen auch gefallen