【问题标题】:Non-blocking lazy-loaded properties in model of MVVMMVVM 模型中的非阻塞延迟加载属性
【发布时间】:2011-06-29 14:33:10
【问题描述】:

我是 MVVM 的新手,如果这个问题有众所周知的解决方案,请见谅。

我们正在构建一堆模型类,它们具有预先加载的一些核心属性,以及一些可以通过进行 Web API 调用按需延迟加载的附加属性(更新:澄清一下,它将是每个延迟加载的属性的 Web API 调用)。

与其拥有多个模型,不如在其中拥有一个具有延迟加载逻辑的模型似乎是明智的。但是,似乎延迟加载的属性在访问时不应该阻塞,这样当 View 绑定到 ViewModel 并绑定到 Model 时,我们不会阻塞 UI 线程。

因此,我正在考虑一种模式,类似于当访问模型上的惰性属性时,它开始异步获取,然后立即返回默认值(例如 null)。当异步获取完成时,它会引发PropertyChanged 事件,以便 ViewModel/View 可以重新绑定到获取的值。

我已经尝试过了,它似乎工作得很好,但我想知道:

  1. 这种方法是否有任何我尚未发现但会随着应用程序复杂性增加而遇到的陷阱?
  2. 是否有针对此问题的现有解决方案,要么内置在框架中,要么被广泛用作 3rd 方框架的一部分?

【问题讨论】:

  • 我能想到的可能问题是,您需要在所有这些惰性加载器上侦听 PropertyChanged 事件,这意味着如果您有一个依赖于多个这些加载器的属性或函数,在执行自己的代码之前,它必须等待它所依赖的所有加载器完成。这可能导致必须编写大量逻辑,否则这些逻辑本来可以编写为单线程调用,该调用结合了在该单独线程中“同步”获取惰性加载程序。
  • @Timothy - 好点子。我已经考虑过这一点,我的感觉是,由于延迟加载数据的性质,任何事情都不太可能依赖于多个延迟数据。多件事情可能会依赖于单个惰性数据,但我认为这不会造成问题。
  • 我使用你上面描述的方法,效果很好。

标签: wpf silverlight mvvm lazy-loading inotifypropertychanged


【解决方案1】:

我过去做过类似的事情,但我一直忘记的一件事是你不能通过任何类型的代码调用你的异步属性并期望它有一个值。

因此,如果我延迟加载 Customer.Products 的列表,我无法在代码隐藏中引用 Customer.Products.Count,因为第一次调用它的值是 NULL 或 0(取决于我是否创建了一个空白集合与否)

除此之外,它对绑定非常有用。我使用 Async CTP 库进行异步调用,我发现这对于这样的事情来说绝对是美妙的。

public ObservableCollection<Products> Products
{
    get
    {
        if (_products == null)
            LoadProductsAsync();

        return _products;
    }
    set { ... }
}

private async void LoadProductsAsync()
{
    Products = await DAL.LoadProducts(CustomerId);
}

更新

我记得我遇到的另一件事是实际上为 NULL 的数据。如果 Customer.Products 实际上从服务器返回了 NULL 值,我需要知道 async 方法已正确运行并且实际值为 null,以便它不会重新运行 async 方法。

如果有人在第一次异步调用完成之前第二次调用 Get 方法,我也不希望异步方法运行两次。

当时我通过为每个异步属性设置一个 Is[AsyncPropertyName]Loading/ed 属性并在第一次异步调用期间将其设置为 true 解决了这个问题,但我对必须为所有异步属性创建一个额外的属性并不满意。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-04-12
    • 1970-01-01
    • 2023-01-30
    • 1970-01-01
    • 2011-08-11
    • 1970-01-01
    • 2012-03-12
    • 2017-12-28
    相关资源
    最近更新 更多