使用 DynamicData 创建派生的 ViewModel 集合,该集合更新现有项目

例如,我有一些指示对象状态的集合的可观察对象(我通过 REST API 定期获取它)。


class User

{

    int Id { get; }

    string Name { get; }

    string Status { get; }

}


IObservable<User> source;

我想创建一个DynamicCache对象并在每次source给我一个新结果时更新它。所以我写道:


var models = new SourceCache<User,int>(user => user.Id);

models.Connect()

      .Transform(u => new UserViewModel() {...})

      ...

      .Bind(out viewModels)

      .Subscribe();


source.Subscribe(ul => models.EditDiff(ul, (a, b) => a.Status == b.Status));

但是现在每次用户更改其状态时,.Transform(...)方法都会创建一个 的新实例UserViewModel,这不是所需的行为。


当具有相同 Id 的源项发生更改而不是每次都创建一个新项时,我能否以某种方式确定更新现有 ViewModel 属性(在派生集合中)的规则?


白衣非少年
浏览 164回答 1
1回答

慕容森

答案是您需要创建一个自定义运算符。我在TransformWithInlineUpdate此处发布了一个要点,您可以将其复制到您的解决方案中。示例用法是:var users = new SourceCache<User, int>(user => user.Id);var transformed =&nbsp; users.Connect()&nbsp; &nbsp; .TransformWithInlineUpdate(u => new UserViewModel(u), (previousViewModel, updatedUser) =>&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; previousViewModel.User = updatedUser;&nbsp; &nbsp; &nbsp; &nbsp; });为了答案的完整性,这里是代码:&nbsp; &nbsp; public static IObservable<IChangeSet<TDestination, TKey>> TransformWithInlineUpdate<TObject, TKey, TDestination>(this IObservable<IChangeSet<TObject, TKey>> source,&nbsp; &nbsp; &nbsp; &nbsp; Func<TObject, TDestination> transformFactory,&nbsp; &nbsp; &nbsp; &nbsp; Action<TDestination, TObject> updateAction = null)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; return source.Scan((ChangeAwareCache<TDestination, TKey>)null, (cache, changes) =>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //The change aware cache captures a history of all changes so downstream operators can replay the changes&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (cache == null)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; cache = new ChangeAwareCache<TDestination, TKey>(changes.Count);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; foreach (var change in changes)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; switch (change.Reason)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case ChangeReason.Add:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; cache.AddOrUpdate(transformFactory(change.Current), change.Key);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case ChangeReason.Update:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (updateAction == null) continue;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var previous = cache.Lookup(change.Key)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .ValueOrThrow(()=> new MissingKeyException($"{change.Key} is not found."));&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //callback when an update has been received&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; updateAction(previous, change.Current);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //send a refresh as this will force downstream operators to filter, sort, group etc&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; cache.Refresh(change.Key);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case ChangeReason.Remove:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; cache.Remove(change.Key);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case ChangeReason.Refresh:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; cache.Refresh(change.Key);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case ChangeReason.Moved:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //Do nothing !&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return cache;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }).Select(cache => cache.CaptureChanges()); //invoke capture changes to return the changeset&nbsp; &nbsp; }
打开App,查看更多内容
随时随地看视频慕课网APP