Mohammed Atef’s Technical blog

Workflow Foundation 4.0 Collections

Introduction

In this post we will see an important built in activities comes with Workflow foundation 4.0., these built-in activities enable you to manipulate a collection in your workflow. this post guide you to do the most required actions for manipulating collections like add,remove and delete items from collection and sorting, searching and clearing the collection.

We will build a console application that demonstrates these activities using a Book Store application.

Building Book Store application
To build the Book Store application you should follow the below steps

1- Create new console application and add System.Activities reference to the new project

2- Open the program.cs file and add the following list of code for declaring BookStoreListItem this class contains a few public properties that store information about an item to be stored.

   1: public class BookStoreListItem
   2:     {
   3:         public string Description { get; set; }
   4:         public int Quantity { get; set; }
   5:         public decimal UnitPrice { get; set; }
   6:         public string Author { get; set; }
   7:         public string BookName { get; set; }
   8:         public BookStoreListItem(string description, int quantity, decimal unitPrice,string author, string bookName)
   9:         {
  10:             Description = description;
  11:             Quantity = quantity;
  12:             UnitPrice = unitPrice;
  13:             BookName = bookName;
  14:             Author = author;
  15:         }
  16:         public BookStoreListItem(string bookName)
  17:         {
  18:             BookName= bookName;
  19:         }
  20:     }

3- Initiate the Workflow by adding the following namespace to the top of program.cs class

using System.Activities.Expressions; now add the following list of code after the closed practices for the main method in the program.cs class

   1: private static Activity CollectionWF()
   2:         {
   3:             // myList is a collection of ListItem objects
   4:             Variable<ICollection<BookStoreListItem>> myList = new Variable<ICollection<BookStoreListItem>>()
   5:             {
   6:                 Name = "MyList",
   7:                 Default = new LambdaValue<ICollection<BookStoreListItem>>
   8:                     (env => new List<BookStoreListItem>())
   9:             };
  10:             return new Sequence
  11:             {
  12:                 Variables = { myList },
  13:                 Activities =
  14:                 {
  15:                     new WriteLine
  16:                     {
  17:                         Text = "Workflow starting..."
  18:                     },
  19:                     new AddToCollection<BookStoreListItem>
  20:                     {
  21:                         Collection = myList,
  22:                         Item = new LambdaValue<BookStoreListItem>
  23:                         (env => new BookStoreListItem("New WorkFlow 4.0 book", 5, 50,"Mohammed", "WorkFlow 4.0"))
  24:                     },
  25:                     new AddToCollection<BookStoreListItem>
  26:                     {
  27:                         Collection = myList,
  28:                         Item = new LambdaValue<BookStoreListItem>
  29:                         (env => new BookStoreListItem("New Linq 4.0 book", 3, 30,"Sherif", "LINQ 4.0"))
  30:                     },
  31:                     new AddToCollection<BookStoreListItem>
  32:                     {
  33:                         Collection = myList,
  34:                         Item = new LambdaValue<BookStoreListItem>
  35:                         (env => new BookStoreListItem("New Windows Communication Foundation 4.0 book", 8, 80,"Atef", "WCF 4.0"))
  36:                     },
  37:                     new AddToCollection<BookStoreListItem>
  38:                     {
  39:                         Collection = myList,
  40:                         Item = new LambdaValue<BookStoreListItem>
  41:                         (env => new BookStoreListItem("Visual studio 2010 book", 15, 40,"Khalid", "VS 2010"))
  42:                     },
  43:                     new WriteLine
  44:                     {
  45:                         Text = "Workflow ended"
  46:                     }
  47:                 }
  48:             };
  49:         }

This workflow defines a variable that is a collection of BookStoreListItem classes named myList. The variable can be any typeof collection that supports the ICollection interface.the LambdaValue Represents a lambda expression used as an r-value, which supports binding of In arguments so it is bind the default value of myList with the returned new instance of BookStoreListItem class .

After that we are going to build the sequence activity for our workflow and the sequence activity will have the following activities

a- writeline activity that printing “Workflow starting…”

b- four AddToCollection activity that used for adding new item of BookStoreListItem to myList

c- another writeline activity to print “Workflow ended…”

4- Now we need to invoke the workflow, so please add the following lines of code in the main method at program.cs class

   1: WorkflowInvoker.Invoke(CollectionWF());
   2: Console.WriteLine("Press ENTER to exit");
   3: Console.ReadLine();

These few line of code used to invoke the workflow by calling collectionWF into the Invoke method.

If you have run the application now you will find the following lines printed

Workflow starting…

Workflow ended…

Press ENTER to exit

5- Printing Collection , we will provide a way to display the contents of the books list, to do that right-click the project and choose Add new Item and select Class, For the class name, enter PrintBooksList.cs. The implementation of this class is shown in Listing below

   1: using System;
   2: using System.Activities;
   3: using System.Collections.Generic;
   4: namespace WFFBookStoreApp
   5: {
   6:     public sealed class PrintBooksList: CodeActivity
   7:     {
   8:         public InArgument<ICollection<BookStoreListItem>> Collection { get; set; }
   9:
  10:         protected override void Execute(CodeActivityContext context)
  11:         {
  12:             ICollection<BookStoreListItem> list =
  13:             this.Collection.Get<ICollection<BookStoreListItem>>(context);
  14:             if (list.Count == 0)
  15:             {
  16:                 Console.WriteLine("The Book list is empty");
  17:             }
  18:             else
  19:             {
  20:                 foreach (BookStoreListItem l in list)
  21:                 {
  22:                     Console.WriteLine("Book Named {0} has the following information :", l.BookName);
  23:                     Console.WriteLine("(Description:{0} ,Quantity: {1},Price: {2} ,Author {3})",
  24:                     l.Description,l.Quantity.ToString(), l.UnitPrice, l.Author);
  25:                 }
  26:                 Console.WriteLine();
  27:             }
  28:         }
  29:     }
  30: }

This custom activity receives the collection as an input argument. It expects a collection of BookStoreListItem classes. the overridden execute method first check if the list empty or not, if yes it is printing the book list is empty message, else it is loop throw the list and print each book item information, this code is very simple you can understand but if you do not know how to create custom activity please visit the following link WFF 4.0 custom activity.

6- To use this custom activity, Open the program.cs file and add the following activity definition to the collectionWF () method before the final writeline activity

   1: new PrintBooksList
   2:                     {
   3:                         Collection=myList
   4:                     },

If you run the application now you will find the following message printed

clip_image002

7- Sorting the collection, we will provide a way to sort the books list by book price, to do that right-click the project and choose Add new Item and select Class, For the class name, enter SortBooksList.cs. The implementation of this class is shown in Listing below

   1: using System;
   2: using System.Activities;
   3: using System.Collections.Generic;
   4: namespace WFFBookStoreApp
   5: {
   6:     public sealed class SortBooksList : CodeActivity
   7:     {
   8:         public InOutArgument<ICollection<BookStoreListItem>> Collection { get; set; }
   9:         protected override void Execute(CodeActivityContext context)
  10:         {
  11:             ICollection<BookStoreListItem> tempList = this.Collection.Get<ICollection<BookStoreListItem>>(context);
  12:             if (tempList.Count > 0)
  13:             {
  14:                 List<BookStoreListItem> sortedList = new List<BookStoreListItem>(tempList);
  15:                 ItemComparer c = new ItemComparer();
  16:                 sortedList.Sort(c as IComparer<BookStoreListItem>);
  17:                 Collection.Set(context, sortedList as ICollection<BookStoreListItem>);
  18:             }
  19:         }
  20:     }
  21:     public class ItemComparer : IComparer<BookStoreListItem>
  22:     {
  23:         public int Compare(BookStoreListItem x, BookStoreListItem y)
  24:         {
  25:             // Handle null arguments
  26:             if (x == null && y == null)
  27:                 return 0;
  28:             if (x == null)
  29:                 return -1;
  30:             if (y == null)
  31:                 return 1;
  32:             // Perform comparison based on the priority
  33:             if (x.UnitPrice == y.UnitPrice)
  34:                 return 0;
  35:             if (x.UnitPrice > y.UnitPrice)
  36:                 return 1;
  37:             else
  38:                 return -1;
  39:         }
  40:     }
  41: }

This custom activity receives the collection as an input argument and return the same argument after sorting it. It expects a collection of BookStoreListItem classes .the overridden Execute() method of this activity takes a collection as both an input and output argument.The Sort() method of the List class is used to perform the sort, but you must supply a class that implements the IComparer interface because the standard implementation will not know how to sort BookStoreListItem objects. The IComparer interface provides a single method called Comparer (), which receives two objects (x and y) as input parameters. It returns 0 if the two objects are equal, 1 if x is greater than y, and -1 if x is less than y.

8- To use this custom activity, Open the Program.cs file and add the following activity definition to the collectionWF () method before the final writeline activity

   1: new SortBooksList
   2: {
   3:     Collection=myList
   4: },
   5: new WriteLine
   6: {
   7:     Text = "Books List sorted by Price"
   8: },
   9: new PrintBooksList
  10: {
  11:     Collection=myList
  12: },

If you run the application now you will find the following message printed

clip_image002[7]

if you have reviewed the printed lines in console, you will find the new books listed after line “books list sorted by price are order desc by price.

9- Searching in the collection, now we are going to use built in activity in Workflow Foundation 4.0 like ExistsInCollection, so we will check if the item found in the book list or not.

As the ExistsInCollection should iterate between books list items so it is require to use Equals() methods which mean we need to implement this method to our BookStoreListItem class, For our purposes, you should consider two items equal if they have the same name,To do that add the following list of code to BookStoreListItem class in program.cs file

   1: public override bool Equals(object obj)
   2: {
   3:     BookStoreListItem i = obj as BookStoreListItem;
   4:     if (i == null)
   5:         return false;
   6:     else
   7:     {
   8:         if (i.BookName == this.BookName)
   9:             return true;
  10:         else
  11:             return false;
  12:     }
  13: }
  14: public override int GetHashCode()
  15: {
  16:     return base.GetHashCode();
  17: }

The Equals() method cast the input object to a BookStoreListItem and returns True if the BookName property matches. When overriding the Equals() method, the compiler expects you to also override the GetHashCode() method. This implementation simply calls the base method

10- Now , we can use ExistsInCollection to do that add the following lines of code before the final writeline activity

   1: public override bool Equals(object obj)
   2:        {
   3:            BookStoreListItem i = obj as BookStoreListItem;
   4:            if (i == null)
   5:                return false;
   6:            else
   7:            {
   8:                if (i.BookName == this.BookName)
   9:                    return true;
  10:                else
  11:                    return false;
  12:            }
  13:        }
  14:        public override int GetHashCode()
  15:        {
  16:            return base.GetHashCode();
  17:        }
  18:

If you have run the application now you will see this line printed before workflow ended

“LINQ 4.0 Book has been added before”

11- Remove item from Collection, Workflow Foundation 4.0 has activity named RemoveFromCollection that is responsible for removing item from collection it very easy in implementation, we will use it to remove book named “LINQ 4.0“,to do that add the following line of code before the final writeline activity

   1: new WriteLine
   2: {
   3:     Text = "Removing LINQ 4.0 book from Books Store..."
   4: },
   5: new RemoveFromCollection<BookStoreListItem>()
   6: {
   7:     Collection = myList,
   8:     Item = new LambdaValue<BookStoreListItem>
   9:         (env => new BookStoreListItem("LINQ 4.0"))
  10: },
  11: new PrintBooksList()
  12: {
  13:     Collection = myList
  14: },

if you have run the application now you will see the following lines printed before workflow ended line

clip_image002[9]

12- Clearing the collection, Workflow Foundation 4.0 has built in activity to clear collection named ClearCollection to use this activity add the following lines of code before the final writeline activity

   1: new ClearCollection<BookStoreListItem>()
   2: {
   3:     Collection = myList
   4: },
   5: new PrintBooksList()
   6: {
   7:     Collection = myList
   8: },

If you have run the application now you will find line printed before workflow ended that says

“The book list is Empty”

Conclusion:

I was trying to learn you how WFF 4.0 are manipulation with collection,you can download The complete implementation of that post from here and you can return back to workflow posts list here

Back to other Workflow Foundation 4.0  posts

I Hope that helped

Advertisements

September 26, 2010 - Posted by | .Net 2010 | , , , , , ,

1 Comment »

  1. […] Workflow Foundation 4.0 Collections […]

    Pingback by Workflow Foundation 4.0 « Mohammed Atef’s Technical blog | September 26, 2010 | Reply


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: