好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

如何在调用WCF服务之前弹出一个确认框?

如何在调用WCF服务之前弹出一个确认框?

昨天有人在微博上问我如下一个问题:

老蒋,客户端调用wcf的一个接口函数时,有没有什么办法可以先弹出一个确认框,确认后再执行调用。因为这个接口函数再很多地方都执行了调用,所以我想在某个入口进行统一地弹出一个确认框...

其实这个问题可以通过WCF的扩展来完成,具体来说这个扩展涉及到一个我们不太常用的组件“InteractiveChannelInitializer”,在我的《WCF全面解析》中对它有过概括性的介绍。InteractiveChannelInitializer实现了接口 IInteractiveChannelInitializer ,从名称可以看出这是一个“交互性”的“信道初始化器”,在一般情况下我们用它来动态地指定客户端调用凭证(比如在弹出的登录对话框中输入用户名和密码)。而上面这个问题就可以通过自定义InteractiveChannelInitializer来实现,我为此写了一个简单的实例(源代码从 这里 下载)。

如下所示的是实例的运行界面。我们以Windows Form应用的方式编写了一个“计算器”,计算结果通过调用WCF服务来获取。在每次调用服务之前都会弹出一个确认对话框,真正的服务调用只有在用户确认之后方能进行。

用于实现“服务调用确认”的自定义InteractiveChannelInitializer(InvocationConfirmationInteractiveChannelInitializer)定义如下。我们在BeginDisplayInitializationUI方法中弹出一个确认对话框,并将用户的确认选择封装到一个简单的AsyncResult对象中返回。在EndDisplayInitializationUI方法中,通过AsyncResult对象确认用户是否取消本次服务调用,如果是则抛出一个自定义的InvocationCancelException异常。

    1:   public   class  InvocationConfirmationInteractiveChannelInitializer : IInteractiveChannelInitializer
    2:  {
    3:       public   const   string  ConfirmMessage =  "程序执行过程涉及到WCF服务调用,是否继续?" ;
    4:       public  IAsyncResult BeginDisplayInitializationUI(IClientChannel channel, AsyncCallback callback,  object  state)
    5:      {
    6:           bool  cancel = MessageBox.Show(ConfirmMessage,  "WCF服务调用确认" , MessageBoxButtons.YesNo) == DialogResult.No;
    7:           return   new  SimpleAsynsResult(cancel);
    8:      }
    9:   
   10:       public   void  EndDisplayInitializationUI(IAsyncResult result)
   11:      {
   12:          SimpleAsynsResult asyncResult = (SimpleAsynsResult)result;
   13:           if (( bool )asyncResult.AsyncState)
   14:          {
   15:               throw   new  InvocationCancelException( "WCF服务调用被取消" );
   16:          }
   17:      }
   18:  }
   19:   
   20:   public   class  SimpleAsynsResult:IAsyncResult
   21:  {
   22:       public  SimpleAsynsResult( object  state)
   23:      {
   24:           this .AsyncState = state;
   25:      }
   26:   
   27:       public   object  AsyncState { get;  private  set; }
   28:       public  WaitHandle AsyncWaitHandle { get;  private  set; }
   29:       public   bool  CompletedSynchronously
   30:      {
   31:          get {  return   true ; }
   32:      }
   33:       public   bool  IsCompleted
   34:      {
   35:          get {  return   true ; }
   36:      }
   37:  }

我们通过一个自定义的ContractBehavior(InvocationConfirmationBehaviorAttribute )将上面自定义的InvocationConfirmationInteractiveChannelInitializer应用到客户端运行时。如下面的代码片断所示,在实现的ApplyClientBehavior方法中,我们创建了一个InvocationConfirmationInteractiveChannelInitializer对象并将其添加到客户端运行时的InteractiveChannelInitializers集合中。

    1:  [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface)]
    2:   public   class  InvocationConfirmationBehaviorAttribute : Attribute, IContractBehavior
    3:  {
    4:       public   void  AddBindingParameters(ContractDescription contractDescription, ServiceEndpoint endpoint, BindingParameterCollection bindingParameters) { }
    5:       public   void  ApplyClientBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, ClientRuntime clientRuntime)
    6:      {
    7:          clientRuntime.InteractiveChannelInitializers.Add( new  InvocationConfirmationInteractiveChannelInitializer());
    8:      }
    9:       public   void  ApplyDispatchBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, DispatchRuntime dispatchRuntime) { }
   10:       public   void  Validate(ContractDescription contractDescription, ServiceEndpoint endpoint) { }
   11:  }

以特性形式定义的InvocationConfirmationBehaviorAttribute直接以如下的方式直接应用到作为服务契约的ICalcualtor接口中:

    1:  [ServiceContract(Name =  "CalculatorService" , Namespace = "http://www.artech.com/" )]
    2:  [InvocationConfirmationBehavior]
    3:   public   interface  ICalculator
    4:  {
    5:      [OperationContract]
    6:       double  Add( double  x,  double  y);
    7:  }

那么在进行服务调用的时候,确认对话框会自动弹出来。如果用户选择终止当前服务调用,那么InvocationCancelException异常会被抛出来,我们只需要捕捉该类型的异常即可。如下所示的是“=”按钮的Click事件代码:

    1:   public   partial   class  Form1 : Form
    2:  {
    3:       //其他成员 
    4:       private   void  buttonCalculate_Click( object  sender, EventArgs e)
    5:      {
    6:           this .textBoxResult.Text =  string .Empty;
    7:           using  (ChannelFactory<ICalculator> channelfactory =  new  ChannelFactory<ICalculator>( "calculatorservice" ))
    8:          {
    9:              ICalculator calculator = channelfactory.CreateChannel();
   10:               try 
   11:              {
   12:                   double  op1 =  double .Parse( this .textBoxOp1.Text);
   13:                   double  op2 =  double .Parse( this .textBoxOp2.Text);
   14:                   double  result = calculator.Add(op1,op2);
   15:                   this .textBoxResult.Text = result.ToString();
   16:              }
   17:               catch  (InvocationCancelException)
   18:              {
   19:              }
   20:               catch  (Exception ex)
   21:              {
   22:                  MessageBox.Show(ex.Message);
   23:              }
   24:          }
   25:      }
   26:  }

作者: Artech
出处: http://artech.cnblogs.com/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

分类:  [02] 编程技巧

作者: Leo_wl

    

出处: http://www.cnblogs.com/Leo_wl/

    

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

版权信息

查看更多关于如何在调用WCF服务之前弹出一个确认框?的详细内容...

  阅读:37次