0

我正在用 C# 编写一个 .NET 库,用于使用 HTTP 通过其 JSON RPC 接口与XBMC进行通信。

我编写并发布了一个初步版本,但一切都是同步完成的。然后,我出于自己的目的将库重新编码为异步的,因为我正在/正在为 WP7 构建 XBMC 遥控器

我现在想发布新的异步库,但想在我发布之前确保它整洁。

由于异步性质,用户发起请求,提供与我的委托匹配的回调方法,然后在收到响应后处理响应。

我遇到的问题是,在库中,我在请求的生命周期内跟踪 RequestState 对象,它包含 http 请求/响应以及用户回调等作为成员变量,如果只有一种类型的对象就可以了回来了,但根据用户所说的,他们可能会返回歌曲列表或电影列表等。

我目前的实现使用一个单一的委托 ResponseDataRecieved 它有一个参数是一个简单的对象 - 因为这只有我使用我知道哪些方法返回什么以及当我处理响应时我将所述对象转换为我知道的类型它真的是 - 列表,列表等。

第三方不应该这样做 - 委托签名应该包含正确类型的对象。因此,对于可以返回给第三方的每种类型的响应数据,我都需要一个委托 - 具体问题是,我如何在内部优雅地处理这个问题 - 我是否有一堆不同的 RequestState 对象,每个对象都有不同的成员变量为不同的代表?这并不“感觉”正确。我只是不知道如何优雅而干净地做到这一点。

4

2 回答 2

0

首先想到的是泛型:ResponseDataRecieved<T>其中 T 是回调中预期的类型。但是,您可以将回调保存为捕获的变量。例如:

public delegate void CallBackA(int i);
public delegate void CallBackB(string s);

public class RequestHandler
{
    public void QueueRequestA(CallBackA callback)
    {
        Task.Factory.StartNew(() =>
                                  {
                                      int ret = 0;
                                      //ret = get stuff of type A from server
                                      callback(ret); //callback is captured here
                                  });
    }

    public void QueueRequestB(CallBackB callback)
    {
        Task.Factory.StartNew(() =>
                                  {
                                      string str = "";
                                      //str = get stuff of typw B from server
                                      callback(str); //callback is captured here
                                  });
    }
}
于 2011-01-03T08:56:01.017 回答
0

如果我理解正确,您有一个提供多种方法的接口,每种方法都采用基本相同类型的委托,但获取不同类型的参数作为输入。像这样的东西:

GetListOfSongs(..., delegate(List<Song> result) { ... });
GetListOfMovies(..., delegate(List<Movie> result) { ... });

并且您担心代理签名会随着接口中的方法一起出现?

如果是这种情况,那么泛型就是您要寻找的。事实上,如果您的委托签名与我的示例匹配——即接受一个输入参数,不返回任何值——您想要的委托类型已经存在于 BCL 中。它被称为Action<T>。您可以像这样声明上面的方法:

GetListOfSongs(..., Action<List<Song>> callback);
GetListOfMovies(..., Action<List<Movie>> callback);

而且您仍然只有一个委托类型,即Action<T>.

现在,如果您需要传递多个参数,您仍然可以使用。存在最多 16 个输入参数的 Action 版本(尽管它们的签名开始看起来有点花哨:)Action<T1, T2, T3 ...>

如果您希望您的回调也返回一个您将在基础设施中的某处使用的值,那么Func<T, TResult>您的朋友是您的朋友(T 是输入参数的类型,TResult 是您将从委托返回的值的类型)。

作为奖励,我建议您不要List<T>在界面中公开。如果您真的认为您的所有客户都需要列表操作,请使用IList<T>,但请考虑ICollection<T>或即使IEnumerable<T>他们不需要。

于 2011-01-02T11:43:46.567 回答