今天看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);
}
}
}