我想获取IdStream
的最新值,并在命令Execute
操作中使用它。
public IObservable<Option<Guid>> IdStream { get; }
IdStream = documentStream.OfType<DocumentOpened().Select(x => x.Document.Id.Some())
.Merge(documentStream.OfType<DocumentClosed().Select(x => Option<Guid>.None()));
var saveCommand = ReactiveCommand.Create(() => Save(id), CanExecute);
我曾尝试使用 https://stackoverflow.com/a/31168822/7779560 的答案,并得到了类似的内容:
var saveCommand = ReactiveCommand.Create(() => { }, CanExecute);
saveCommand.WithLatestFrom(IdStream, (_, id) => id)
.Subscribe(id => Save(id));
它有效,但在这种情况下我不能使用IsExecuting和ThrownExceptions命令的功能(它们仅用于在命令创建期间作为Execute传递的空操作)。
UPD:
执行顺序:
IdStream
创建documentStream
处理DocumentOpened
事件(获取一些Id值 - 我检查了它)saveCommand
执行我怎样才能实现它?
UPD 2:我还需要等待命令体内的方法(例如SaveAsync
)。
答案 0 :(得分:2)
这对你有用吗?重播将保留最新发布的价值。执行该命令时,它将获取最新值,Take(1)取消订阅,因为您只需要一个值,然后将其推送到Save;
[Test]
public void ExecuteUsingLastProducedValue()
{
Subject<string> producer = new Subject<string>();
IObservable<bool> CanExecute = Observable.Return(true);
IObservable<string> IdStream = producer;
string SaveCalledWith = String.Empty;
Func<string, Task> SaveAsync = (id) =>
{
SaveCalledWith = id;
return Task.Delay(0);
};
// IdStream creating
var connectedIdStream =
IdStream
.Replay(1);
connectedIdStream
.Connect();
//Command creating
var command = ReactiveCommand.CreateFromObservable(() =>
{
return connectedIdStream
.Take(1)
.Do(async id =>
{
await SaveAsync(id);
});
}
, CanExecute);
//Alternate way
//Command creating
//var command = ReactiveCommand.CreateFromObservable(() =>
//{
// return connectedIdStream
// .Take(1)
// .SelectMany(id => SaveAsync(id).ToObservable());
//}
//, CanExecute);
//documentStream processes DocumentOpened event (get some Id value - I checked it)
producer.OnNext("something random");
producer.OnNext("working");
//At this point Save still hasen't been called so just verifiyng it's still empty
Assert.AreEqual(String.Empty, SaveCalledWith);
//trigger execution of command
command.Execute(Unit.Default).Subscribe();
//Verified Saved Called With is called
Assert.AreEqual(SaveCalledWith, "working");
}
答案 1 :(得分:0)
[Fact]
public void ExecuteUsingLastProducedValue()
{
Subject<string> producer = new Subject<string>();
IObservable<bool> CanExecute = Observable.Return(true);
IObservable<string> IdStream = producer;
string SaveCalledWith = String.Empty;
Func<string, Task> SaveAsync = (id) =>
{
SaveCalledWith = id;
return Task.Delay(0);
};
// IdStream creating
var connectedIdStream =
IdStream
.Replay(1);
connectedIdStream
.Connect();
//Command creating
var command = ReactiveCommand.Create(() => { } , CanExecute);
connectedIdStream.Sample( command )
.Subscribe( id => SaveAsync(id) );
//documentStream processes DocumentOpened event (get some Id value - I checked it)
producer.OnNext("something random");
producer.OnNext("working");
//At this point Save still hasen't been called so just verifiyng it's still empty
SaveCalledWith.Should().Be( String.Empty );
//trigger execution of command
command.Execute(Unit.Default).Subscribe();
//Verified Saved Called With is called
SaveCalledWith.Should().Be( "working");
}
(我用XUnit重写了,因为我手边有这个)
这是一个稍微简化和扩展的测试用例,其中一些代码被我推荐的代码替换。
[Fact]
public void ExecuteUsingLastProducedValue()
{
var producer = new Subject<string>();
var canExecute = Observable.Return(true);
var saveCalledWith = String.Empty;
void Save(string id) => saveCalledWith = id;
var rcommand = ReactiveCommand.Create(() => { } , canExecute);
// When cast to ICommand ReactiveCommand has a
// more convienient Execute method. No need
// to Subscribe.
var command = (ICommand) rcommand;
producer
.Sample( rcommand )
.Subscribe( Save );
//documentStream processes DocumentOpened event (get some Id value - I checked it)
producer.OnNext("something random");
producer.OnNext("working");
//At this point Save still hasen't been called so just verifiyng it's still empty
saveCalledWith.Should().Be( String.Empty );
//trigger execution of command
command.Execute( Unit.Default );
//Verified Saved Called With is called
saveCalledWith.Should().Be( "working");
command.Execute( Unit.Default );
saveCalledWith.Should().Be( "working");
producer.OnNext("cat");
saveCalledWith.Should().Be( "working");
command.Execute( Unit.Default );
saveCalledWith.Should().Be( "cat");
producer.OnNext("dog");
saveCalledWith.Should().Be( "cat");
command.Execute( Unit.Default );
saveCalledWith.Should().Be( "dog");
}
答案 2 :(得分:0)
您可以将流的最新值存储在ObservableAsPropertyHelper<>
属性中,并在命令中使用它。
您的班级属性如下所示:
public IObservable<Option<Guid>> IdStream { get; }
private ObservableAsPropertyHelper<Option<Guid>> _currentId;
public Option<Guid> CurrentId => _currentId.Value;
你的构造函数会像这样连接:
IdStream.ToProperty(this, x => x.CurrentId, out _currentId);
var saveCommand = ReactiveCommand.Create(() => Save(CurrentId), CanExecute);
您可能希望为CurrentId
属性提供默认值。您可以在ToProperty()
电话中执行此操作。