Szy*_*iga 2 c# events asynchronous webclient windows-phone-7
我有一个JSON API,我希望我的应用程序访问.所以我写了一个方法.
public List<Books> GetBooks()
{
var webclient = new WebClient();
var jsonOutput = webclient.DownloadString(
new Uri("http://someplace.com/books.json")
);
return ParseJSON(jsonOutput);//Some synchronous parsing method
}
Run Code Online (Sandbox Code Playgroud)
现在我需要将DonwloadString更改为DownloadStringAsync.我找到了这个教程.
但这似乎太复杂了.我试图让这个工作,但我不确定这是否是正确的方法.也许有一种更简单,更好的方法?
所有要求您订阅事件以获取结果的异步操作都很痛苦.我认为最简单的方法是将事件处理抽象为一些很好的扩展方法,并使用连续传递样式(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);
}
Run Code Online (Sandbox Code Playgroud)
这种方法隐藏了的创作WebClient,所有的事件处理,以及部署和退订事后清理的东西了.
它的使用方式如下:
var uri = new Uri("http://someplace.com/books.json");
uri.DownloadString(t =>
{
// Do something with the string
});
Run Code Online (Sandbox Code Playgroud)
现在,这可用于创建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);
});
}
Run Code Online (Sandbox Code Playgroud)
它的使用方式如下:
this.GetBooks(new Uri("http://someplace.com/books.json"), books =>
{
// Do something with `List<Books> books`
});
Run Code Online (Sandbox Code Playgroud)
那应该是整洁而简单的.
现在,您可能希望通过以下两种方式扩展它.
您可以创建ParseJSON具有此签名的重载:
void ParseJSON(string text, Action<List<Books>> action)
Run Code Online (Sandbox Code Playgroud)
然后你可以完全取消这个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
}));
Run Code Online (Sandbox Code Playgroud)
现在你有一个漂亮的流畅风格,可组合的操作集.作为奖励,下载的字符串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);
});
}
Run Code Online (Sandbox Code Playgroud)
然后,您可以将非错误处理DownloadString扩展方法替换为:
public static void DownloadString(this Uri uri, Action<string> action)
{
uri.DownloadString(action, null);
}
Run Code Online (Sandbox Code Playgroud)
然后使用错误处理方法,你会这样做:
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`
});
Run Code Online (Sandbox Code Playgroud)
最终结果应该相当简单易用和阅读.我希望这有帮助.
| 归档时间: |
|
| 查看次数: |
1321 次 |
| 最近记录: |