今天看Curator源碼時發現其請求ZooKeeper集群時內部封裝了重試機制,代碼如下:
Stat resultStat = RetryLoop.callWithRetry ( client.getZookeeperClient(), new Callable() { @Override public Stat call() throws Exception { return client.getZooKeeper().setData(path, data, version); } } );
public static利用Java中的CallableT callWithRetry(CuratorZookeeperClient client, Callable proc) throws Exception { T result = null; RetryLoop retryLoop = client.newRetryLoop(); while ( retryLoop.shouldContinue() ) { try { client.internalBlockUntilConnectedOrTimedOut(); //調用帶返回值的Callable方法 result = proc.call(); retryLoop.markComplete(); } catch ( Exception e ) { retryLoop.takeException(e); } } return result; }
因為我要開發C#的對應的版本,所以也需要將一段代碼(請求ZooKeeper的代碼)傳遞到這樣一個具備失敗重試功能的函數中運行,由於我對C#不是很熟悉,所以能想到的只有通過聲明一個代理,再定義一個操作ZooKeeper的函數,將這個函數賦值給代理,將代理傳遞到具備重試功能的函數中。
但是這種方式勢必要定義一個代理,還要顯式申明一個方法賦值給代理,代碼量大且不是很優雅,所以我就開始深入了解C#這方面如何實現,然後發現了C#2.0引入的匿名方法,以及C#3.0引入的用於取代匿名方法的Lambda表達式,是編寫內聯代碼的首選。下面先提供我寫的一段測試代碼,可以完成我的需求,之後再講解何謂匿名方法和Lambda表達式。
CustomDelegate.cs:
using System; using System.Collections.Generic; using System.Linq; namespace DelegateAndLamda { delegate string CustomDelegate(string material); }PizzaMaker.cs:
namespace DelegateAndLamda { class PizzaMaker { public static void makePizza(string material, CustomDelegate bake) { //前面有一堆固定流程,但是接下來烘烤方法不同 string result = bake(material); Console.WriteLine(result); } } }Program.cs
namespace DelegateAndLamda { class Program { public static void Main(string[] args) { //在 2.0 之前的 C# 版本中,聲明委托的唯一方法是使用命名方法 CustomDelegate bake = new CustomDelegate(bakePizza); PizzaMaker.makePizza(張三的Pizza, bake); // C# 2.0 引入了匿名方法 PizzaMaker.makePizza(李四的Pizza, delegate(string material) { return String.Format(將{0}烘烤成面包, material); } ); //在 C# 3.0 及更高版本中,Lambda 表達式取代了匿名方法,作為編寫內聯代碼的首選方式 PizzaMaker.makePizza(季義欽的Pizza, material => { return String.Format(將{0}烘烤成意大利pizza, material); }); } public static string bakePizza(string material) { return String.Format(將{0}烘烤成西瓜, material); } } }