为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

C#
白衣非少年 2022-06-19 16:55:18
例如,我有一些指示对象状态的集合的可观察对象(我通过 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 属性(在派生集合中)的规则?
查看完整描述

1 回答

?
慕容森

TA贡献1853条经验 获得超18个赞

答案是您需要创建一个自定义运算符。我在TransformWithInlineUpdate此处发布了一个要点,您可以将其复制到您的解决方案中。示例用法是:


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


var transformed =  users.Connect()

    .TransformWithInlineUpdate(u => new UserViewModel(u), (previousViewModel, updatedUser) =>

        {

            previousViewModel.User = updatedUser;

        });

为了答案的完整性,这里是代码:


    public static IObservable<IChangeSet<TDestination, TKey>> TransformWithInlineUpdate<TObject, TKey, TDestination>(this IObservable<IChangeSet<TObject, TKey>> source,

        Func<TObject, TDestination> transformFactory,

        Action<TDestination, TObject> updateAction = null)

    {

        return source.Scan((ChangeAwareCache<TDestination, TKey>)null, (cache, changes) =>

            {

                //The change aware cache captures a history of all changes so downstream operators can replay the changes

                if (cache == null)

                    cache = new ChangeAwareCache<TDestination, TKey>(changes.Count);


                foreach (var change in changes)

                {

                    switch (change.Reason)

                    {

                        case ChangeReason.Add:

                            cache.AddOrUpdate(transformFactory(change.Current), change.Key);

                            break;

                        case ChangeReason.Update:

                        {

                            if (updateAction == null) continue;


                            var previous = cache.Lookup(change.Key)

                                .ValueOrThrow(()=> new MissingKeyException($"{change.Key} is not found."));

                            //callback when an update has been received

                            updateAction(previous, change.Current);


                            //send a refresh as this will force downstream operators to filter, sort, group etc

                            cache.Refresh(change.Key);

                        }

                            break;

                        case ChangeReason.Remove:

                            cache.Remove(change.Key);

                            break;

                        case ChangeReason.Refresh:

                            cache.Refresh(change.Key);

                            break;

                        case ChangeReason.Moved:

                            //Do nothing !

                            break;

                    }

                }

                return cache;


            }).Select(cache => cache.CaptureChanges()); //invoke capture changes to return the changeset

    }


查看完整回答
反对 回复 2022-06-19
  • 1 回答
  • 0 关注
  • 162 浏览

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号