使用直接方法创建可观察量



我需要回忆一些数据调用连接到Web服务的方法。

问题:假设我需要根据此远程收集的信息更新标签控件的内容文本。在重新收集所有这些数据之前,我将无法显示标签。

期望:我想先用默认文本显示标签,当我收到此信息时,我想更新标签内容(请不要将此描述视为糟糕的代码,我正在尝试简要介绍我的真实情况)。

我想创建这些方法的可观察序列。然而,这些方法没有相同的签名。例如:

int GetInt() {
    return service.GetInt();
}
string GetString() {
    return service.GetString();
}
string GetString2 {
    return service.GetString2();
}

这些方法不是async的。

  1. 是否可以创建这些方法的可观察序列?

  2. 我该如何创建它?

  3. 然而,哪个是实现我的目标的最佳选择?

创建自定义可观察序列可以使用 Observable.Create 来实现。使用您的要求的示例如下所示:

private int GetInt()
{
    Thread.Sleep(1000);
    return 1;
}
private string GetString()
{
    Thread.Sleep(1000);
    return "Hello";
}
private string GetString2()
{
    Thread.Sleep(2000);
    return "World!";
}
private IObservable<string> RetrieveContent()
{
    return Observable.Create<string>(
        observer =>
        {
            observer.OnNext("Default Text");
            int value = GetInt();
            observer.OnNext($"Got value {value}. Getting string...");
            string string1 = GetString();
            observer.OnNext($"Got string {string1}. Getting second string...");
            string string2 = GetString2();
            observer.OnNext(string2);
            observer.OnCompleted();
            return Disposable.Empty;
        }
    );
}

请注意我是如何通过在每个 GetXXX 方法中引入Thread.Sleep调用来模拟网络延迟的。为了确保您的 UI 在订阅此可观察量时不会挂起,您应该按如下方式订阅:

IDisposable subscription = RetrieveContent()
  .SubscribeOn(TaskPoolScheduler.Default)
  .ObserveOn(DispatcherScheduler.Current)
  .Subscribe(text => Label = text);

此代码使用 .SubscribeOn(TaskPoolScheduler.Default) 扩展方法使用 TaskPool 线程启动可观察序列,并将被调用 Thread.Sleep 阻止,但由于这不是 UI 线程,因此 UI 将保持响应。然后,为了确保我们更新 UI 线程上的 UI,我们使用".ObserveOn(DispatcherScheduler.Current)",在设置 (数据绑定) Label 属性之前调用对 UI 线程的更新。

希望这就是您要找的,但如果没有,请发表评论,我会尽力进一步提供帮助。

我会考虑为您的服务创建一个包装类,以将值公开为单独的可观察量。

因此,从服务接口开始:

public interface IService
{
    int GetInt();
    string GetString();
    string GetString2();
}

。然后你写ServiceWrapper

public class ServiceWrapper : IService
{
    private IService service;
    private Subject<int> subjectGetInt = new Subject<int>();
    private Subject<string> subjectGetString = new Subject<string>();
    private Subject<string> subjectGetString2 = new Subject<string>();
    public ServiceWrapper(IService service)
    {
        this.service = service;
    }
    public int GetInt()
    {
        var value = service.GetInt();
        this.subjectGetInt.OnNext(value);
        return value;
    }
    public IObservable<int> GetInts()
    {
        return this.subjectGetInt.AsObservable();
    }
    public string GetString()
    {
        var value = service.GetString();
        this.subjectGetString.OnNext(value);
        return value;
    }
    public IObservable<string> GetStrings()
    {
        return this.subjectGetString.AsObservable();
    }
    public string GetString2()
    {
        var value = service.GetString2();
        this.subjectGetString2.OnNext(value);
        return value;
    }
    public IObservable<string> GetString2s()
    {
        return this.subjectGetString2.AsObservable();
    }
}

现在,假设您当前的服务称为 Service ,您将编写以下代码来设置内容:

IService service = new Service();
ServiceWrapper wrapped = new ServiceWrapper(service); // Still an `IService`
var subscription =
    Observable
        .Merge(
            wrapped.GetInts().Select(x => x.ToString()),
            wrapped.GetStrings(),
            wrapped.GetString2s())
        .Subscribe(x => label.Text = x);
IService wrappedService = wrapped;

现在将wrappedService而不是service传递给您的代码。它仍在调用底层service代码,因此无需重写,但您仍然可以获得所需的可观察量。

这实际上是一组四个装饰器模式。

相关内容

  • 没有找到相关文章

最新更新