WCF Dispose具体应用方法介绍

WCF开发框架,在编程人员眼中是一个比较重要的开发工具。那么,熟练的应用这一工具,对于开发人员来说是很重要的。下面就来看看WCF Dispose的一些基本概念。

  在实际应用中实现WCF用户密码认证 
  WCF操作Stream传递size过大消息 
  WCF集合元素基本概念详解 
  全方位解析WCF应用程序 
  技巧掌握之WCF获取客户端IP

  毫无疑问,在.NET Framework中,一个资源(尤其是非托管资源)通常都需要实现IDisposable接口。一旦实现了该接口,我们就可以使用using语句来管理资源,这是最便捷的方式。但是,一旦在using语句中抛出了异常,就可能不会正确完成资源的回收,尤其是连接,很可能会一直打开,既占用了通道和端口,还可能出现资源的浪费,从而影响系统的性能和稳定性。

  微软推荐的最佳实践是抛弃using语句,转而利用 try/catch(/finally)语句。它要求在try语句中调用Close()方法,而在catch中调用Abort()方法。在新闻中已经说明了Close()与Abort()方法的区别,即后者可以强制地关闭客户端,包括关闭客户端连接,释放资源。由于Close()方法可能会抛出 CommunicationException和TimeoutException异常,通常的客户端代码应该是这样:


  
  var myClient = new MyClient();   
  try   
  {   
  //其他代码   
  myClient.Close();   
  }   
  catch (CommunicationException)   
  {   
  myClient.Abort();   
  }   
  catch (TimeoutException)   
  {   
  myClient.Abort();   
  }   
  catch (Exception)   
  {   
  myClient.Abort();   
  throw;   
  } 

  在最后增加对Exception异常的捕获很有必要,因为我们不知道Close()方法会否抛出某些不可预知的异常,例如 OutOfMemoryException等。新闻中提到Steve Smith的方法其实就是对这段冗长代码的封装,封装方式是采用扩展方法,扩展的类型为ICommunicationObject。这是因为所有的客户端对象都实现了ICommunicationObject接口。以下是Steve Smith的扩展方法代码:

  public static class Extensions  
  {  
  public static void CloseConnection
  (this ICommunicationObject myServiceClient)  
  {  
  if (myServiceClient.State != 
  CommunicationState.Opened)  
  {  
  return;  
  }   
  try  
  {  
  myServiceClient.Close();  
  }  
  catch (CommunicationException ex)  
  {  
  Debug.Print(ex.ToString());  
  myServiceClient.Abort();  
  }  
  catch (TimeoutException ex)  
  {  
  Debug.Print(ex.ToString());  
  myServiceClient.Abort();  
  }  
  catch (Exception ex)  
  {  
  Debug.Print(ex.ToString());  
  myServiceClient.Abort();  
  throw;  
  }  
  }  
  } 

  利用WCF Dispose扩展方法,在本应调用Close()方法的地方,代替为CloseConnection()方法,就可以避免写冗长的catch代码。而使用 Lambda表达式的方式可以说是独辟蹊径,使用起来与using语法大致接近。实现方法是定义一个静态方法,并接受一个 ICommunicationObject对象与Action委托:

  public class Util  
  {  
  public static void Using<T>
  (T client, Action action)  
  where T : ICommunicationObject  
  {  
  try  
  {  
  action(client);  
  client.Close();  
  }  
  catch (CommunicationException)  
  {  
  client.Abort();  
  }  
  catch (TimeoutException)  
  {  
  client.Abort();  
  }  
  catch (Exception)  
  {  
  client.Abort();  
  throw;  
  }  
  }  
  } 

  使用时,可以将原本的客户端代码作为Action委托的Lambda表达式传递给Using方法中:

  Util.Using(new 
  MyClient(), client =>
  {  
  client.SomeWCFOperation();  
  //其他代码;  
  }); 

  还有一种方法是定义一个自己的ChannelFactory,让其实现IDisposable接口,并作为ChannelFactory的Wrapper 类。在该类中定义Close()和WCF Dispose方法时,考虑到异常抛出的情况,并在异常抛出时调用Abort()方法。这样我们就可以在using 中使用自定义的ChannelFactory类。例如:

  public class MyChannelFactory:IDisposable  
  {  
  private ChannelFactory m_innerFactory;  
  public MyChannelFactory(ChannelFactory factory)  
  {  
  m_innerFactory = factory;  
  }  
  ~MyChannelFactory()  
  {  
  Dispose(false);  
  }  
  public void Close()  
  {  
  Close(TimeSpan.FromSeconds(10));  
  }  
  public void Close(TimeSpan span)  
  {  
  if (m_innerFactory != null)  
  {  
  if (m_innerFactory.State != 
  CommunicationState.Opened)  
  {  
  return;  
  }  
  try  
  {  
  m_innerFactory.Close(span);  
  }  
  catch (CommunicationException)  
  {  
  m_innerFactory.Abort();  
  }  
  catch (TimeOutException)  
  {  
  m_innerFactory.Abort();  
  }  
  catch (Exception)  
  {  
  m_innerFactory.Abort();  
  throw;  
  }  
  }  
  }  
  private void Dispose(booling disposing)  
  {  
  if (disposing)  
  {  
  Close();  
  }  
  }  
  void IDisposable.Dispose()  
  {  
  Dispose(true);  
  GC.SuppressFinalize(this);  
  }  
  } 

  其实,新闻中提到采用代理模式的方式与此实现相同。总之,万变不离其宗,所有WCF Dispose替代方案的设计本质都是对冗长的try/catch/finally的一次包装,从而有效地实现重用,保证系统的安全、性能与稳定性。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值