4

所以我有一个使用 MVVM 模式(Caliburn.Micro)的 WPF 应用程序。我得到了视图和视图模型,基本上缺少的是数据。数据将从 WCF 服务、本地存储或内存/缓存“按需”检索 - 原因是允许离线模式并避免不必要的服务器通信。另一个要求是异步检索数据,因此 UI 线程不会被阻塞。

所以我正在考虑创建某种视图模型用来请求数据的“AssetManager”:

_someAssetManager.GetSomeSpecificAsset(assetId, OnGetSomeSpecificAssetCompleted)

请注意,这是一个异步调用。我遇到了一些不同的问题。如果不同的视图模型(大致)同时请求相同的资产,我们如何确保我们不做不必要的工作并且它们都获得了我们可以绑定的相同对象?

不确定我的方法是否正确。我一直在浏览 Reactive Framework - 但我不知道如何在这种情况下使用它。关于我可以使用的框架/技术/模式的任何建议?这似乎是一个相当普遍的情况。

4

4 回答 4

4
Dictionary<int, IObservable<IAsset>> inflightRequests;

public IObservable<IAsset> GetSomeAsset(int id)
{
    // People who ask for an inflight request just get the
    // existing one
    lock(inflightRequests) {
        if inflightRequests.ContainsKey(id) {
            return inflightRequests[id];
        }
    }

    // Create a new IObservable and put in the dictionary
    lock(inflightRequests) { inflightRequests[id] = ret; }

    // Actually do the request and "play it" onto the Subject. 
    var ret = new AsyncSubject<IAsset>();
    GetSomeAssetForReals(id, result => {
        ret.OnNext(id);
        ret.OnCompleted();

        // We're not inflight anymore, remove the item
        lock(inflightRequests) { inflightRequests.Remove(id); }
    })

    return ret;
}
于 2012-04-10T06:30:33.853 回答
1

我在传递接收数据时调用的委托的方法调用方面取得了成功。您可以通过检查确定请求是否正在发生的布尔字段来分层要求让每个人都使用相同的数据(如果当前正在发生请求)。我会保留需要调用的委托的本地集合,以便在最终接收到数据时,包含要调用的委托的类可以迭代它们,传入新接收的数据。

这些方面的东西:

public interface IViewModelDataLoader{
    void LoadData(AssignData callback);
}

public delegate void AssignData(IEnumerable<DataObject> results);

然后,实际实现此接口的类可以记录数据完成时通知谁(假设是单例模型):

public class ViewModelDataLoader : IViewModelDataLoader{
    private IList<AssignData> callbacksToCall;
    private bool isLoading;

    public void LoadData(AssignData callback){
        callbacksToCall.add(callback);
        if (isLoading) { return; }

        // Do some long running code here
        var data = something;
        // Now iterate the list
        foreach(var item in callbacksToCall){
           item(data);
        }
        isLoading = false;
    }
 }
于 2012-04-09T15:49:25.263 回答
1

使用代理模式和事件,您可以提供同步和异步数据。让您的代理返回同步调用的缓存值,并在您接收异步数据时通过事件通知视图模型。代理还可以设计为跟踪数据请求和限制服务器连接(例如“引用计数”调用、请求的数据/接收的数据标志等)

于 2012-04-09T16:30:37.193 回答
1

我会这样设置你AssetManager

public interface IAssetManager
{
    IObservable<IAsset> GetSomeSpecificAsset(int assetId);
}

在内部,您需要返回Subject<IAsset>异步填充的 a 。做对了,每次调用GetSomeSpecificAsset.

于 2012-04-10T06:24:41.360 回答