У меня есть класс, который принимает наблюдаемое в своем конструкторе, затем подписывается на него и делает некоторые вещи, устанавливает свойства и т. д. Сам класс является наблюдаемым.
Я хочу подписаться на мой источник, наблюдаемый только в том случае, если кто-то подписан на мой класс, но я не могу понять, как это сделать.
public MyClass : IObservable<MyResult>
{
private readonly Subject<MyResult> _subject = new Subject<MyResult>();
private readonly IConnectableObservable<MySource> _source;
public MyClass(IObservable<MySource> source)
{
_source = source
//All my logic to set properties and such
//goes here as a side effect, instead of in a subscription...
.Do(...)
//I hope that by publishing, side effects will happen only once...
.Publish();
}
public IDisposable Subscribe(IObserver<MyResult> observer)
{
return new CompositeDisposable(
_source.Subscribe(/*
don't have anything to do here,
just subscribing to make sure I'm subscribed to source...
(this can't be the right way to do it)
*/),
_subject.Subscribe(observer));
}
}
ОБНОВИТЬ
@Scott: я понимаю, почему реализация IObservable будет анти-шаблоном. My Class
должен потреблять один наблюдаемый объект и предоставляет 3 в качестве свойств (первоначально наиболее часто используемый наблюдаемый объект должен был быть возвращен самим MyClass
, но я думаю, что иметь его в качестве свойства может быть лучше.
То, что я пытаюсь написать, - это наблюдаемая ICommand. Я знаю, что некоторые из них существуют, но это скорее способ выучить Rx...
public class ObservableCommand<T> : ICommand
{
private readonly ISubject<T> _executeRequests = new Subject<T>();
private readonly ISubject<T> _canExecuteRequests = new Subject<T>();
public IObservable<bool> CanExecuteChanges { get; private set; }
public IObservable<T> CanExecuteRequests { get; private set; }
public IObservable<T> ExecuteRequests { get; private set; }
public ObservableCommand(IObservable<bool> canExecute)
{
var source = canExecute.DistinctUntilChanged()
//How do I dispose of subscription later?
//I have this fear that I'm going to have a chain of references,
//and my entire app will never get GC'd!
var subscription = source.Subscribe(
o => {
if (CanExecuteChanged != null)
CanExecuteChanged(this, EventArgs.Empty);
});
CanExecuteChanges = source;
CanExecuteRequests = _canExecuteRequests.AsObservable();
ExecuteRequests = _executeRequests.AsObservable();
}
#region ICommand Members
public bool CanExecute(object parameter)
{
_canExecuteRequests.OnNext(parameter is T ? (T)parameter : default(T));
}
public event EventHandler CanExecuteChanged;
public void Execute(object parameter)
{
_executeRequests.OnNext(parameter is T ? (T)parameter : default(T));
}
#endregion
}