程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> WF4.0中四種自定義類型活動

WF4.0中四種自定義類型活動

編輯:關於.NET

工作流中的活動就像用戶自定義的控件,將許多的功能封裝起來用。WF4.0中提供了四種可繼承的活動 類:CodeActivity 、AsyncCodeActivity、Activity、NativeActivity。這幾種活動都有自己使用的適合 場合,正確的使用這些活動將非常有利。

1、CodeActivity

WF4.0中的活動是樹形結構的,創建葉子活動最簡單是方式就是使用CodeActivity ,它的邏輯都放在 一個方法:Execute 裡面,這個也是四種活動中最簡單的一種。這裡用一個簡單的自定活動HttpGet來說 明怎麼使用CodeActivity。HttpGet的功能是從網絡上抓取數據。

public sealed class HttpGet : CodeActivity<string>
     {
         public InArgument<string> Uri { get; set; }
         protected override string Execute(CodeActivityContext context)
         {
             WebRequest request = HttpWebRequest.Create(this.Uri.Get (context));
             using (WebResponse response = request.GetResponse())
             {
                 //read everything response.GetResponseStream() as one  string
                 using (StreamReader reader = new StreamReader (response.GetResponseStream()))
                 {
                     return reader.ReadToEnd();
                 }
             }
         }
     }

public InArgument<string> Uri { get; set; }是工作流中的一個屬性,相當於類的屬性,不 過取它的值與類有點不同,你需要使用:Uri.Get(context))或者 context.GetValue(Uri),Execute方法 是這個活動的邏輯,特別注意CodeActivityContext context參數,這是WF的上下文,非常有用。

如何使用這個活動:

HttpGet fetchMsn = new HttpGet
      {
          Uri = "http://www.msn.com"
      };
      string msnContent = WorkflowInvoker.Invoke<string>(fetchMsn);
      Console.WriteLine(msnContent);

2、AsyncCodeActivity

AsyncCodeActivity 類似CodeActivity ,只是它是使用了 Begin/EndExecute 取代了CodeActivity 的Execute 方法。BeginExecute 開始一個異步操作,無需等待它完成,就返回IAsyncResult對象 。當這 個操作完成的時候,就執行EndExecute 方法放回結果。HttpGet 能這樣實現,請注意 CodeActivityContext換成了AsyncCodeActivityContext:

class HttpGet : AsyncCodeActivity<string>
     {
         public InArgument<string> Uri { get; set; }
         protected override IAsyncResult BeginExecute(AsyncCodeActivityContext  context, AsyncCallback callback, object state)
         {
             WebRequest request = HttpWebRequest.Create(this.Uri.Get (context));
             context.UserState = request;
             return request.BeginGetResponse(callback, state);
         }
         protected override string EndExecute(AsyncCodeActivityContext  context, IAsyncResult result)
         {
             WebRequest request = (WebRequest)context.UserState;
             using (WebResponse response = request.EndGetResponse (result))
             {
                 using (StreamReader reader = new StreamReader (response.GetResponseStream()))
                 {
                     return reader.ReadToEnd();
                 }
             }
         }
     }

3、Activity

Activity可以以組合的方式定義活動。開發人員可以使用已有活動構建一個活動樹來實現這個活動。 如果你需要在工作流中完成一些復雜的邏輯,可以使用這種方式。這裡用一個flowchart為例:

public sealed class FlowChartActivity : Activity
     {
         public string promoCode { get; set; }
         public int numKids { get; set; }
         public FlowChartActivity(string promoCode, int numKids)
         {
             this.promoCode = promoCode;
             this.numKids = numKids;
             base.Implementation = new Func<Activity> (CreateBody);
         }
         Activity CreateBody()
         {
             Variable<string> promo = new Variable<string> {  Default = promoCode};
             Variable<int> numberOfKids = new Variable<int> {  Default = numKids };
             Variable<double> discount = new Variable<double> ();
             DelegateInArgument<DivideByZeroException> ex = new  DelegateInArgument<DivideByZeroException>();
             FlowStep discountNotApplied = new FlowStep
             {
                 Action = new WriteLine
                 {
                     DisplayName = "WriteLine: Discount not  applied",
                     Text = "Discount not applied"
                 },
                 Next = null
             };
             FlowStep discountApplied = new FlowStep
             {
                 Action = new WriteLine
                 {
                     DisplayName = "WriteLine: Discount  applied",
                     Text = "Discount applied "
                 },
                 Next = null
             };
             FlowDecision flowDecision = new FlowDecision
             {
                 Condition = ExpressionServices.Convert<bool> ((ctx) => discount.Get(ctx) > 0),
                 True = discountApplied,
                 False = discountNotApplied
             };
             FlowStep singleStep = new FlowStep
             {
                 Action = new Assign
                 {
                     DisplayName = "discount = 10.0",
                     To = new OutArgument<double> (discount),
                     Value = new InArgument<double>(10.0)
                 },
                 Next = flowDecision
             };
             FlowStep mnkStep = new FlowStep
             {
                 Action = new Assign
                 {
                     DisplayName = "discount = 15.0",
                     To = new OutArgument<double> (discount),
                     Value = new InArgument<double>(15.0)
                 },
                 Next = flowDecision
             };
             FlowStep mwkStep = new FlowStep
             {
                 Action = new TryCatch
                 {
                     DisplayName = "Try/Catch for Divide By Zero  Exception",
                     Try = new Assign
                     {
                         DisplayName = "discount = 15 + (1  - 1/numberOfKids)*10",
                         To = new OutArgument<double> (discount),
                         Value = new InArgument<double> ((ctx) => (15 + (1 - 1 / numberOfKids.Get(ctx)) * 10))
                     },
                     Catches = 
                     {
                          new  Catch<System.DivideByZeroException>
                          {
                              Action = new  ActivityAction<System.DivideByZeroException>
                              {
                                  Argument = ex,
                                  DisplayName =  "ActivityAction - DivideByZeroException",
                                  Handler =
                                      new  Sequence
                                      {
                                          DisplayName = "Divide by Zero Exception Workflow",
                                          Activities =
                                          {
                                             new WriteLine() 
                                             {
                                                  DisplayName = "WriteLine: DivideByZeroException",
                                                  Text = "DivideByZeroException: Promo code is MWK - but number of kids =  0" 
                                             },
                                             new Assign<double>
                                             {
                                                  DisplayName = "Exception - discount = 0", 
                                                  To = discount,
                                                  Value = new InArgument<double>(0)
                                             }
                                          }
                                      }
                              }
                          }
                     }
                 },
                 Next = flowDecision
             };
             FlowStep discountDefault = new FlowStep
             {
                 Action = new Assign<double>
                 {
                     DisplayName = "Default discount assignment:  discount = 0",
                     To = discount,
                     Value = new InArgument<double>(0)
                 },
                 Next = flowDecision
             };
             FlowSwitch<string> promoCodeSwitch = new  FlowSwitch<string>
             {
                 Expression = promo,
                 Cases =
                 {
                    { "Single", singleStep },
                    { "MNK", mnkStep },
                    { "MWK", mwkStep }
                 },
                 Default = discountDefault
             };
             Flowchart flowChart = new Flowchart
             {
                 DisplayName = "Promotional Discount Calculation",
                 Variables = { discount, promo, numberOfKids },
                 StartNode = promoCodeSwitch,
                 Nodes = 
                 {
                     promoCodeSwitch, 
                     singleStep, 
                     mnkStep, 
                     mwkStep, 
                     discountDefault, 
                     flowDecision, 
                     discountApplied, 
                     discountNotApplied
                 }
             };
             return flowChart;
         }
      }

調用:

WorkflowInvoker.Invoke(new FlowChartActivity("MWK", 2));

注意這個自定義活動實現與前面兩個的區別,它在構造函數中指定實現活動的方法,而這個方法返回 Activity類型。

4、NativeActivity

這個活動是四種活動中最強大的一個,實現起來非常的靈活。WF4.0中內置的Sequence 、While 、If 、Parallel 等活動都繼承此類。如果前面三種都實現不了,這個活動可能能實現你需要的功能。例如自 定一個While:

public sealed class MyWhile : NativeActivity
     {
         Collection<Variable> variables;
         public MyWhile()
         {
             this.variables = new Collection<Variable>();
         }
         public Collection<Variable> Variables
         {
             get
             {
                 return this.variables;
             }
         }
         public Activity<bool> Condition  { get; set; }
         public Activity Body { get; set; }
         protected override void CacheMetadata(NativeActivityMetadata  metadata)
         {
             //call base.CacheMetadata to add the Variables, Condition,  and Body to the activity's metadata
             base.CacheMetadata(metadata);
             if (this.Condition == null)
             {
                 //MyWhile requires a Condition expression so - add  a validation error if one isn't present
                 metadata.AddValidationError(string.Format("While {0}  requires a Condition", this.DisplayName));
                 return;
             }
         }
         protected override void Execute(NativeActivityContext context)
         {
             InternalExecute(context, null);
         }
         void InternalExecute(NativeActivityContext context, ActivityInstance  instance)
         {
             //schedule the Condition for evaluation
             context.ScheduleActivity(this.Condition, new  CompletionCallback<bool>(OnEvaluateConditionCompleted));
         }
         void OnEvaluateConditionCompleted(NativeActivityContext context,  ActivityInstance instance, bool result)
         {
             if (result)
             {
                 if (this.Body != null)
                 {
                     //if the Condition evaluates to true and  the Body is not null
                     //schedule the Body with the InternalExecute  as the CompletionCallback
                     context.ScheduleActivity(this.Body,  InternalExecute);
                 }
             }
         }
     }

簡單的看下這個MyWhile,很簡單分兩個部分看:屬性和方法。屬性有variables、Condition、和Body 。方法有構造函數、 CacheMetadata、Execute、OnEvaluateConditionCompleted。CacheMetadata、 Execute 覆蓋父類的方法。ScheduleActivity完成之後執行OnEvaluateConditionCompleted。

總結:WF4.0的資料不多,但是相對WF3.0和3.5簡單很多,自定義活動是非常重要學習內容。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved