所有需要您订阅事件得到的结果仅仅是痛苦的异步操作。我认为最简单的方法是将事件处理抽象为一些漂亮的扩展方法,并使用延续传递样式(CPS)来处理结果。
所以,第一件事就是下载字符串创建一个扩展方法:
public static void DownloadString(this Uri uri, Action<string> action)
{
if (uri == null) throw new ArgumentNullException("uri");
if (action == null) throw new ArgumentNullException("action");
var webclient = new WebClient();
DownloadStringCompletedEventHandler handler = null;
handler = (s, e) =>
{
var result = e.Result;
webclient.DownloadStringCompleted -= handler;
webclient.Dispose();
action(result);
};
webclient.DownloadStringCompleted += handler;
webclient.DownloadStringAsync(uri);
}
这种方法隐藏掉WebClient
的创作,所有的事件的处理,以及部署和退订干净的东西之后。
它这样使用:
var uri = new Uri("http://someplace.com/books.json");
uri.DownloadString(t =>
{
// Do something with the string
});
现在,这可以用来创建GetBooks
方法。那就是:
public void GetBooks(Uri uri, Action<List<Books>> action)
{
if (action == null) throw new ArgumentNullException("action");
uri.DownloadString(t =>
{
var books = ParseJSON(t);
action(books);
});
}
它这样使用:
this.GetBooks(new Uri("http://someplace.com/books.json"), books =>
{
// Do something with `List<Books> books`
});
这应该是整洁和简单。
现在,您可能希望扩展这一点。
您可以创建的ParseJSON
过载有此签名:
void ParseJSON(string text, Action<List<Books>> action)
然后,你可以用GetBooks
方法做掉干脆只写:
var uri = new Uri("http://someplace.com/books.json");
uri.DownloadString(t => ParseJSON(t, books =>
{
// Do something with `List<Books> books`
// `string t` is also in scope here
}));
现在你有一个很好的整齐流畅的风格,可组合的操作集。作为奖励,下载的字符串t
也在范围之内,因此您可以轻松记录它或进行其他处理(如果需要的话)。
您可能还需要处理异常和这些可以添加像这样:
public static void DownloadString(
this Uri uri,
Action<string> action,
Action<Exception> exception)
{
if (uri == null) throw new ArgumentNullException("uri");
if (action == null) throw new ArgumentNullException("action");
var webclient = (WebClient)null;
Action<Action> catcher = body =>
{
try
{
body();
}
catch (Exception ex)
{
ex.Data["uri"] = uri;
if (exception != null)
{
exception(ex);
}
}
finally
{
if (webclient != null)
{
webclient.Dispose();
}
}
};
var handler = (DownloadStringCompletedEventHandler)null;
handler = (s, e) =>
{
var result = (string)null;
catcher(() =>
{
result = e.Result;
webclient.DownloadStringCompleted -= handler;
});
action(result);
};
catcher(() =>
{
webclient = new WebClient();
webclient.DownloadStringCompleted += handler;
webclient.DownloadStringAsync(uri);
});
}
然后,您可以取代非错误处理DownloadString
扩展方法有:
public static void DownloadString(this Uri uri, Action<string> action)
{
uri.DownloadString(action, null);
}
再到使用错误处理方法你可以这样做:
var uri = new Uri("http://someplace.com/books.json");
uri.DownloadString(t => ParseJSON(t, books =>
{
// Do something with `List<Books> books`
}), ex =>
{
// Do something with `Exception ex`
});
最终结果应该相当简单的使用和阅读。我希望这有帮助。
你想包围什么? –
那么最后我想要一个名为GetBooksAsync()的异步方法,我也有GetBooksCompleted。 –