我有一个容器类Project
,里面有很多IItem
个。项目可以在项目启动之前添加项目。然后不能再添加任何项目,除非它被停止。
每个项目都可以通过其IsActive
属性激活和停用。
public interface IItem
{
bool IsActive { get; set;}
}
public interface IFoo : IItem
{
}
public class Foo : IFoo
{
public bool IsActive { get; set;}
}
public interface IBar : IItem
{ }
public class Bar : IBar
{
public bool IsActive { get; set;}
}
public class Project
{
public Project(params IItem [] items)
{
Items = new List<IItem>(items);
}
public List<IItem> Items { get;}
}
我还有两个可观察项目,一个用于项目状态,另一个用于更改任何项目。为了这个例子的目的,我已经用主题模拟了这些
var projectIsRunningObservable = new Subject<bool>();
var projectItemChangedObservable = new Subject<IItem>();
我正在尝试创建一个IObservable<bool>
,它发送一个值,指示是否(至少有一个项目处于活动状态且项目已启动)。如果存在活动项目并且项目已停止,则应该推送false
值。
这是我到目前为止所做的:
void Main()
{
var bar1 = new Bar();
var bar2 = new Bar();
var foo1 = new Foo();
var foo2 = new Foo();
var projectIsRunningObservable = new Subject<bool>();
var projectItemChangedObservable = new Subject<IItem>();
var project = new Project(
bar1, bar2, foo1, foo2);
var observable = Observable.Create<bool>(obs =>
{
IList<IItem> items = null;
var stateObservable = projectIsRunningObservable.StartWith(false).Subscribe(
(state) =>
{
if (!state)
{
items = null;
obs.OnNext(false);
}
else
{
items = project.Items.ToList();
obs.OnNext(items != null && items.Any(i => i.IsActive));
}
},
ex => obs.OnError(ex),
() => obs.OnCompleted());
var itemChangedObservable = projectItemChangedObservable.Subscribe(
x =>
{
obs.OnNext(items != null && items.Any(i => i.IsActive));
}
,
ex => obs.OnError(ex),
() => obs.OnCompleted());
return new CompositeDisposable(stateObservable, itemChangedObservable);
});
var subscr = observable.Subscribe(Console.WriteLine);
Console.WriteLine("Change bar1");
bar1.IsActive = true;
projectItemChangedObservable.OnNext(bar1);
Console.WriteLine("Change bar2");
bar2.IsActive = true;
projectItemChangedObservable.OnNext(bar2);
Console.WriteLine("Change foo1");
foo1.IsActive = true;
projectItemChangedObservable.OnNext(foo1);
Console.WriteLine("Change foo2");
foo2.IsActive = true;
projectItemChangedObservable.OnNext(foo2);
// Start project
Console.WriteLine("Starting project");
projectIsRunningObservable.OnNext(true);
Console.WriteLine("Change bar1");
bar1.IsActive = false;
projectItemChangedObservable.OnNext(bar1);
Console.WriteLine("Change bar2");
bar2.IsActive = false;
projectItemChangedObservable.OnNext(bar2);
Console.WriteLine("Change foo1");
foo1.IsActive = false;
projectItemChangedObservable.OnNext(foo1);
Console.WriteLine("Change foo2");
foo2.IsActive = false;
projectItemChangedObservable.OnNext(foo2);
Console.WriteLine("Change foo2 back to true");
foo2.IsActive = true;
projectItemChangedObservable.OnNext(foo2);
// Stop project
Console.WriteLine("Stopping project");
projectIsRunningObservable.OnNext(false);
Console.WriteLine("Change bar1");
bar1.IsActive = true;
projectItemChangedObservable.OnNext(bar1);
Console.WriteLine("Change bar2");
bar2.IsActive = true;
projectItemChangedObservable.OnNext(bar2);
Console.WriteLine("Change foo1");
foo1.IsActive = true;
projectItemChangedObservable.OnNext(foo1);
Console.WriteLine("Change foo2");
foo2.IsActive = true;
projectItemChangedObservable.OnNext(foo2);
}
这有效,但我不确定这是否是最佳方式,以及是否可以发送多个OnError
和OnCompleted
通知。
答案 0 :(得分:1)
这是component
的一个很好的用例。您应该将Observable.Create
重构为Subject
,并使用Observable
类进行测试。
您可以在Rx Design Guidelines (PDF)中找到后一个问题的答案。第6.2章指出TestScheduler
提供了一些保护措施,使序列遵循Rx契约。
当可观察序列完成时(通过触发OnError或Oncompleted),任何订阅都将自动取消订阅。 任何订阅的观察者实例只会看到一条OnError或OnCompleted消息。不再发送任何消息。这确保了OnNext *(OnError | OnCompleted)的Rx语法?
注意:在指南示例中,它们使用Observable.Create
。在最新的Rx版本中,它已被重构为Observable.CreateWithDisposable
的重载,您可能知道:)