2017-02-23 8 views
2

현재 애플리케이션을위한 마법사 시스템을 구축하고 있으며 ReactiveUI를 사용 중이며 결과로 Rx를 사용하고 있습니다.Reactive Extensions 중첩 계층에 대한 펼치기/스캔 접근 방식

마법사의 각 단계는 IWizardStep<T>을 구현합니다. 여기서 T은 마법사가 최종적으로 생성하는 데이터 형식입니다.

각 단계에는 사용자가 다음 단계로 이동할 수있는 단계가 있어야하기 때문에 데이터 입력을 기반으로 분기 할 수 있습니다.

단계는 유사한 구조를 갖는 생각할 수

: IStepChoice<T> 함께

public interface IWizardStep<T> 
{ 
    IObservable<IStepChoice<T>> NextStepChoice {get;} 
} 

단순히 인 :

들어, 시작부터 종료까지의 전류 경로를 계산하기 위해
public interface IStepChoice<T> 
{ 
    IWizardStep<T> Step {get;} 
    string Reason {get;} 
} 

사용자에게 표시, 나는 시작 단계에서 갈 수 있고, null에 도달 할 때까지 NextStepChoice 체인을 재귀 적으로 따라갈 수 있어야합니다 (유효한 동작이므로 NextStepChoice은 null을 방출하여 t의 끝을 나타냅니다). 그는 마법사).

나는 Observable.Scan을 살펴 봤지만 나에게있어이 재귀를 올바르게 재귀 적으로 수행하는 방법을 찾지 못했습니다.

저는이 부분이 유망 해 보이는 Observable.Generate을 살펴 보았습니다. 유일한 문제는 Generate이 루프를 끊을 때를 결정하는 함수를 사용하지만, 이것을 알아보기 위해 내부 관찰 가능을 평가해야한다는 것입니다.

Observable.Generate(
    new WizardStepChoice<T>(start, null), 
    choice => choice != null, 
    choice => choice.ChosenStep.NextStepChoice, 
    choice => choice); 

이 이상적, 그리고 난 후 출력을 생산하지만,이 IWizardStepChoice<T>보다는 IObservable<IWizardStepChoice<T>>을 때문에 거기 NextStepChoice 선택은 분명 컴파일되지 않는 것입니다.

좀 더 배 중심의 작업이 AggregateScan를 사용에서 그러나이 같은 검토 한 결과, 나는 단지 시작 요소를 가지고, 내가 알라 Generate을 찾고 있어요 펼쳐하지만 나는 할 필요 중첩 된 관찰 가능을 평가할 수 있습니다.

Observable.Create은 내가 활용할 수있는 것일까요? 나는 그것을 시도와 함께 왔어요 :

언뜻 그것은 바로 보이는, 그래서 내가 IWizardStep<T>->IReadOnlyList<IWizardStep<T>>을 원하는 모든 권리 서명이 있지만 작동하지 않는
Path = CurrentStep.Select(_ => Observable.Create<IWizardStep<T>>(async observer => 
{ 
    IWizardStepChoice<T> next = new WizardStepChoice<T>(start, null); 
    observer.OnNext(next.ChosenStep); 
    while (next != null) 
    { 
     next = await next.ChosenStep.NextStepChoice; 
     observer.OnNext(next.ChosenStep); 
    } 
    observer.OnCompleted(); 
    return Disposable.Empty; 
}).Aggregate(new List<IWizardStep<T>>(), 
(l, s) => 
{ 
    l.Add(s); 
    return l; 
})).Switch().Publish().RefCount(); 

; 그것은 발화하고, 나는 단계를 밟을 수 있지만 일단 기다리고 나서 돌아 오지 않으면 멈춘다.

는 내가 가까이있어 느낌이있어, 이것은 스케줄링 문제, 그래서 제 질문은 정말 이것이다 :

  1. 이 문제를 해결하는 가장 좋은 방법은 무엇인가, 내가 닫으 무엇입니까?
  2. 이것이 맞다면 기다리는 데 문제가있는 이유는 무엇이며 어떻게 해결할 수 있습니까?

업데이트

나는 await를 가능성이 그 관찰로 매달려있는 것을 발견 땜질의 약간은 아직했다 (그리고 것되지 않은) 값을 방출 한 후 (대만족). 이제 마법사의 시작 부분에서 각 단계를 초기화하여 해결했습니다.

I했습니다 심지어 정신-확인 IWizardStep<T>에 속성을 추가하여 - 단지에 매여 IWizardStepChoice<T> LatestStepChoice {get;} :

NextStepChoice.Subscribe(c => _latestStepChoice = c);

이 단계 클래스 자체에서 수행되고, 나는 그것의 확인하실 수 있습니다 잘 작동합니다.

는 그러나 아직도이 중단을 기다리고 있습니다, 그래서 시도 :

  1. 그것이 Replay(1) 그래서 값을 얻을 것 .Subscribe()를 호출하는 AWAIT이 만들기 -이 Repeat() 그래서 뭔가가 가입 된 경우에도 그것을 만들기
  2. 작동하지 않았다 새로운 가치를 보게 될 것입니다. 이것은 모든 것을 멈추게 만듭니다. AWAIT이 관찰을 쿼리 할 때, 그것이 내가 Replay(1) 달성 것이라고 생각 무엇을 볼 수있는 최신 값을받을 수 있도록 내가 여기서 뭔가를 누락 분명히

, 내가 원하는; 또한 PublishLast()을 시도했지만 AsyncSubject<T> 동작으로 인해 향후 업데이트가 적용되지 않습니다.

지금은 자체 등록 된 속성을 사용하도록 전환했으나 이상적이지는 않습니다. 도움이 될만한 경우 관찰 가능 항목을 쿼리하는 것으로부터 벗어날 필요가 없습니다. "해킹"이라고 느껴집니다.

+0

당신이 무엇을 찾고 있는지의 서명을 게시 할 수 있습니까? 마법사의 관측이 뜨거워? – Shlomo

+0

@Shlomo @Shlomo 내가 갈 수 있기를 원한다. IWizardStep -> IReadOnlyList > 그 일이 일어 났으므로, 단계 클래스를 스스로 선택하여 관찰 할 수 있고 속성에 접근 할 수 있습니다. – Clint

+0

함수가 재귀 적 데이터 구조에서 재귀 적 데이터 구조 목록으로 이동하는 점은 무엇입니까? – Shlomo

답변

2

재귀 도보 하나의 관찰에 관찰 가능한의 트리를 변환 할 수 있습니다

static IObservable<IWizardStep<T>> Walk<T>(IWizardStep<T> step) 
    { 
     if (step?.NextStepChoice == null) 
      return Observable.Return(step); 

     return step.NextStepChoice.SelectMany(choice => Walk(choice.Step)).StartWith(step); 
    } 

사용법 :

var steps = await Walk(step).ToArray(); 
+0

이것은 내가 거의 끝내었던 것입니다. (종류), 결국 모든 불일치 상태를 하나의 불변 인 상태 객체로 통합 한 다음 그걸 관찰하면서 건설 시간에 필연적 인 열거 형을 수행 할 수 있다는 것을 의미합니다. 기반 재귀 적 워크로드 및 기타 정보를 추출합니다. 또한 스케줄링 문제를 크게 단순화하고 코드를 추론하기가 더 쉬워졌습니다. – Clint