如果数组元素发生变化,则可观察到
Posted
技术标签:
【中文标题】如果数组元素发生变化,则可观察到【英文标题】:Observable if the array element is changed 【发布时间】:2022-01-20 09:06:35 【问题描述】:如何用一行代码写出这段代码?
public class RadGridColumnObservable
public RadGridColumnObservable(RadGridView grid, IMessageBus messageBus)
this.grid = grid;
this.messageBus = messageBus;
public IDisposable Initialize()
CreateStates();
return Observable
.Interval(TimeSpan.FromSeconds(1))
.Subscribe(_ => CheckUp());
//
private readonly RadGridView grid;
private readonly IMessageBus messageBus;
private readonly List<bool> states = new List<bool>();
//
private void CreateStates()
states.Clear();
states.AddRange(grid.Columns.Select(it => it.IsVisible));
private void CheckUp()
if (states.SequenceEqual(grid.Columns.Select(it => it.IsVisible))) return;
CreateStates();
messageBus.Publish(new NotifyMessage(MessageTypes.HistoryColumnsChanged));
想法是:我想检查IsVisible
属性是否改变了。
我不喜欢用这条线:
private readonly List<bool> states = new List<bool>();
【问题讨论】:
"isVisible" 改变了什么值?你需要一些结构来保持值比较 当我隐藏/显示列时,我没有为 RadGridView 找到任何事件,我使用线程将旧列与新列进行比较,以查看“IsVisible”何时更改。代码工作正常,但我想用 Observable 优化它。 您正在使用的网格是 UI 网格吗?如果是这样,您需要发送ObserveOn
以防止出现线程问题。
【参考方案1】:
您可以通过以下方式获取您的 IsVisible
值:
private IObservable<List<bool>> CreateStatesObservable()
return Observable.Interval(TimeSpan.FromSeconds(1))
.Select(_ => grid.Columns.Select(it => it.IsVisible));
然后使用Scan 来跟踪你之前的值:
public void Initialize()
var observable =
CreateStatesObservable()
.Scan(
(prev: default(List<bool>), actual: default(List<bool>)),
(acc, c) => (acc.actual, current))
.Where(values => !values.actual.SequenceEqual(values.prev))
.Select(_ => true);
或者您可以使用Defer 并执行以下操作:
public void Initialize2()
var observable = CreateStatesObservable();
var deferred =
Observable.Defer(
() =>
List<bool> previous = null;
return observable.Select(
values =>
if (previous is null)
previous = values;
return false;
if (!values.SequenceEqual(previous))
previous = values;
return true;
return false;
);
)
.Where(value => value);
这两个选项都应该给你一个 observable,它只在 IsVisible
列之一发生变化时产生一个值。 (该值只是 true
)
编辑:
您也可以将DistinctUntilChanged()
与您自己的IEqualityComparer
一起使用,如下所示:
class ListComparer : IEqualityComparer<List<bool>>
bool IEqualityComparer<List<bool>>.Equals(List<bool>? a, List<bool>? b)
if (a is null && b is null)
return true;
if (a is null || b is null)
return false;
return a.SequenceEqual(b);
int IEqualityComparer<List<bool>>.GetHashCode(List<bool> obj)
return obj.GetHashCode();
然后像这样使用它:
public void Initialize()
var observable =
CreateStatesObservable()
.DistinctUntilChanged(new ListComparer())
.Select(_ => true);
【讨论】:
非常好的答案。非常感谢。 乐于助人:)。现在我再想一想,您也许还可以使用DistinctUntilChanged()
并编写自己的平等比较器来实现 IEqualityComparer<List<bool>>
我用DistinctUntilChanged()
的例子更新了我的答案
+1 我使用 scan 的方法,我测试过 Observable.Defer 并且工作良好。但我认为扫描方法更好。我是 system.reactive 的初学者,但我真的很喜欢这个想法。【参考方案2】:
我认为您可以将您的Initialize()
调整为这样的:
public IDisposable Initialize()
return Observable
.Interval(TimeSpan.FromSeconds(1))
.Select(v => grid.Columns.Select(it => it.IsVisible).ToList())
.Scan((prev: new List<bool>(), actual: new List<bool>()),
(acc, c) => (acc.actual, c))
.Where(it => !it.actual.SequenceEqual(it.prev))
.Subscribe(_ => messageBus.Publish(new NotifyMessage(MessageTypes.HistoryColumnsChanged)));
这应该给你同样的结果,你只需要一次SequenceEqual()
。扫描就在那里,所以你有“当前”和“以前”的值。在你的情况下,你真的不需要在里面做检查。
【讨论】:
【参考方案3】:我现在使用这样的东西:
public class RadGridColumnObservable
public RadGridColumnObservable(RadGridView grid, IMessageBus messageBus)
this.grid = grid;
this.messageBus = messageBus;
public IDisposable Initialize()
return Observable
.Interval(TimeSpan.FromSeconds(1))
.Scan((prev: grid.Columns.Select(it => it.IsVisible).ToList(), actual: grid.Columns.Select(it => it.IsVisible).ToList()),
(acc, c) =>
if (!acc.prev.SequenceEqual(acc.actual))
acc.prev = acc.actual;
acc.actual = grid.Columns.Select(it => it.IsVisible).ToList();
return acc;
)
.Where(it => !it.prev.SequenceEqual(it.actual))
.Subscribe(it => messageBus.Publish(new NotifyMessage(MessageTypes.HistoryColumnsChanged)));
//
private readonly RadGridView grid;
private readonly IMessageBus messageBus;
但我不喜欢,因为我第二次使用“SequenceEqual”。
【讨论】:
以上是关于如果数组元素发生变化,则可观察到的主要内容,如果未能解决你的问题,请参考以下文章