2011-09-14 4 views
2

A, B, C, D, E라고 할 수있는 몇 가지 WCF 호출이 있습니다. SL 응용 프로그램에 있습니다 (따라서 스레드와 조심해야합니다. 등).
A가 완료된 후에 B가 실행되고 C는 동시에 실행될 수 있습니다. 나는 3 명이 모두 끝내고 나서 D가 뛰길 바란다. 또한 조건 (단순한 경우 ...)을 기반으로 E도 실행해야합니다 (위의 항목과 동시에).Rx에서 여러 이벤트를 처리하는 방법 (종속성 포함)

방금 ​​Rx를 다운로드하고이 작업을위한 도구라고 생각합니다. 그러나 나는 아직 모든 연산자와 트릭 등을 파악하지 못했습니다.

이 작업을 수행 할 수 있습니까? 방법? 이에 필요한 운영자를 설명하십시오. 단순화 술의 이러한 서비스의 모든 매개 변수로 문자열 (또는 int)를 가지고 말을하지 말라, 그리고 복잡한 인터페이스를 구현 뭔가를 반환, 그래서 이벤트는 간단한 EventHandlers (제네릭이 아닌 있습니다

편집 추가 할), 핸들러 코드에서 특수 인터페이스로 캐스팅했습니다.
일부 입력은 시작에 사용할 수 있으며, 일부는 내가 계정에 편집을 촬영하고 함께 해결책을 넣었습니다

+0

5 회의 WCF 통화에 대한 서명을 제공 할 수 있습니까?Rx는 당신이 요구하는 것을 할 수 있지만 서명을 알지 못하면 당신에게 좋은 대답을주기가 조금 어렵습니다. – Enigmativity

+0

@Enigmativity : 정보를 추가하기 위해 질문을 편집했습니다. – TDaver

답변

2

(예를 들어, B의 입력 문자열 A의 결과를 기초로 계산) 이전 서비스의 결과에서 온다.

Microsoft는 Silverlight에서 간단한 WCF 호출을 작성하기가 어렵다고 말합니다. 비동기 호출로부터 리턴 데이터를 얻기 위해 이벤트를 처리하는 것은 고통 스럽다.

"copy-and-paste"보일러 - 플레이트 코드를 약간 사용하면 Rx가 복잡성을 제거하는 훌륭한 작업을 수행했다고합니다. 여기

내가 최종 클라이언트 코드로 내놓았다 무엇 :이 코드는 내가 기대했던만큼 꽤하지 않습니다

 var service = new Service1Client(); 

     var abs = 
      from a in service.AObservable("a") 
      from b in service.BObservable(a) 
      select new { a, b }; 

     var cs = service.CObservable("c"); 

     var abcs = abs.Zip(cs, (ab, c) => new { ab.a, ab.b, c }); 

     var ds = 
      from abc in abcs 
      from d in service.DObservable(abc.a, abc.b, abc.c) 
      select String.Format(
       "A={0} B={1} C={2} D={3}", 
       abc.a, abc.b, abc.c, d); 

     var condition = true; 

     var es = from e in condition 
        ? service.EObservable("e") 
        : Observable.Empty<string>() 
       select String.Format("E={0}", e); 

     ds.Merge(es).ObserveOnDispatcher() 
        .Subscribe(r => this.label1.Content += " " + r); 

한편으로, 그러나 다른 한편으로 내가 얻을 수 있다고 생각하지 않습니다 그것은 더 낫다. 다행히 요구 사항이 어떻게 충족되고 있는지 확인할 수 있기를 바랍니다.

이제 나쁜 소식은 모든 서비스 프록시에 대해 확장 메서드를 만들어야한다는 것입니다. EventArgs이 정의 된 방식은 특정 서비스 참조 클래스를 확장 메서드에 대한 매개 변수로 사용하지 않고도 결과를 가져올 수 없습니다.

코드가 거의 수정과 함께 대부분 "복사하여 붙여 넣기"되어 있지만 장점은 있습니다.

또한 사용할 매개 변수만큼 확장 메서드를 하나 더 만드는 것이 필요합니다.

여기 내 샘플 코드를 정의하는 데 필요한 확장 방법은 다음과 같습니다

public static class Service1ClientEx 
{ 
    public static Func<IObservable<R>> ToObservableFunc<EA, R>(this Service1Client service, Action<Service1Client> async, Action<Service1Client, EventHandler<EA>> ah, Action<Service1Client, EventHandler<EA>> rh, Func<EA, R> resultSelector) 
     where EA : System.ComponentModel.AsyncCompletedEventArgs 
    { 
     return() => Observable.Create<R>(o => 
     { 
      var response = 
       from ep in Observable.FromEventPattern<EA>(h => ah(service, h), h => rh(service, h)) 
       select resultSelector(ep.EventArgs); 

      var subscription = response.Take(1).Subscribe(o); 

      async(service); 

      return subscription; 
     }).ObserveOn(Scheduler.ThreadPool); 
    } 

    public static Func<P0, IObservable<R>> ToObservableFunc<P0, EA, R>(this Service1Client service, Action<Service1Client, P0> async, Action<Service1Client, EventHandler<EA>> ah, Action<Service1Client, EventHandler<EA>> rh, Func<EA, R> resultSelector) 
     where EA : System.ComponentModel.AsyncCompletedEventArgs 
    { 
     return p0 => Observable.Create<R>(o => 
     { 
      var response = 
       from ep in Observable.FromEventPattern<EA>(h => ah(service, h), h => rh(service, h)) 
       select resultSelector(ep.EventArgs); 

      var subscription = response.Take(1).Subscribe(o); 

      async(service, p0); 

      return subscription; 
     }).ObserveOn(Scheduler.ThreadPool); 
    } 

    public static Func<P0, P1, IObservable<R>> ToObservableFunc<P0, P1, EA, R>(this Service1Client service, Action<Service1Client, P0, P1> async, Action<Service1Client, EventHandler<EA>> ah, Action<Service1Client, EventHandler<EA>> rh, Func<EA, R> resultSelector) 
     where EA : System.ComponentModel.AsyncCompletedEventArgs 
    { 
     return (p0, p1) => Observable.Create<R>(o => 
     { 
      var response = 
       from ep in Observable.FromEventPattern<EA>(h => ah(service, h), h => rh(service, h)) 
       select resultSelector(ep.EventArgs); 

      var subscription = response.Take(1).Subscribe(o); 

      async(service, p0, p1); 

      return subscription; 
     }).ObserveOn(Scheduler.ThreadPool); 
    } 

    public static Func<P0, P1, P2, IObservable<R>> ToObservableFunc<P0, P1, P2, EA, R>(this Service1Client service, Action<Service1Client, P0, P1, P2> async, Action<Service1Client, EventHandler<EA>> ah, Action<Service1Client, EventHandler<EA>> rh, Func<EA, R> resultSelector) 
     where EA : System.ComponentModel.AsyncCompletedEventArgs 
    { 
     return (p0, p1, p2) => Observable.Create<R>(o => 
     { 
      var response = 
       from ep in Observable.FromEventPattern<EA>(h => ah(service, h), h => rh(service, h)) 
       select resultSelector(ep.EventArgs); 

      var subscription = response.Take(1).Subscribe(o); 

      async(service, p0, p1, p2); 

      return subscription; 
     }).ObserveOn(Scheduler.ThreadPool); 
    } 

    public static Func<P0, P1, P2, P3, IObservable<R>> ToObservableFunc<P0, P1, P2, P3, EA, R>(this Service1Client service, Action<Service1Client, P0, P1, P2, P3> async, Action<Service1Client, EventHandler<EA>> ah, Action<Service1Client, EventHandler<EA>> rh, Func<EA, R> resultSelector) 
     where EA : System.ComponentModel.AsyncCompletedEventArgs 
    { 
     return (p0, p1, p2, p3) => Observable.Create<R>(o => 
     { 
      var response = 
       from ep in Observable.FromEventPattern<EA>(h => ah(service, h), h => rh(service, h)) 
       select resultSelector(ep.EventArgs); 

      var subscription = response.Take(1).Subscribe(o); 

      async(service, p0, p1, p2, p3); 

      return subscription; 
     }).ObserveOn(Scheduler.ThreadPool); 
    } 

    public static IObservable<string> AObservable(this Service1Client service, string data) 
    { 
     return service 
      .ToObservableFunc<string, ACompletedEventArgs, string>((s, p0) => s.AAsync(p0), (s, h) => s.ACompleted += h, (s, h) => s.ACompleted -= h, ea => ea.Result) 
      .Invoke(data); 
    } 

    public static IObservable<string> BObservable(this Service1Client service, string data) 
    { 
     return service 
      .ToObservableFunc<string, BCompletedEventArgs, string>((s, p0) => s.BAsync(p0), (s, h) => s.BCompleted += h, (s, h) => s.BCompleted -= h, ea => ea.Result) 
      .Invoke(data); 
    } 

    public static IObservable<string> CObservable(this Service1Client service, string data) 
    { 
     return service 
      .ToObservableFunc<string, CCompletedEventArgs, string>((s, p0) => s.CAsync(p0), (s, h) => s.CCompleted += h, (s, h) => s.CCompleted -= h, ea => ea.Result) 
      .Invoke(data); 
    } 

    public static IObservable<string> DObservable(this Service1Client service, string dataA, string dataB, string dataC) 
    { 
     return service 
      .ToObservableFunc<string, string, string, DCompletedEventArgs, string>((s, p0, p1, p2) => s.DAsync(p0, p1, p2), (s, h) => s.DCompleted += h, (s, h) => s.DCompleted -= h, ea => ea.Result) 
      .Invoke(dataA, dataB, dataC); 
    } 

    public static IObservable<string> EObservable(this Service1Client service, string data) 
    { 
     return service 
      .ToObservableFunc<string, ECompletedEventArgs, string>((s, p0) => s.EAsync(p0), (s, h) => s.ECompleted += h, (s, h) => s.ECompleted -= h, ea => ea.Result) 
      .Invoke(data); 
    } 
} 

내가 말했듯이, 고통.

Silverlight에서 WCF와 함께 Rx를 사용하려면 이러한 유형의 확장 메서드를 만들지 않아도되지만 일단 만든 후에는 클라이언트 코드가 훨씬 더 쉽게 작업 할 수 있다는 느낌입니다.

더 자세한 설명이 필요하면 알려주세요.

+0

확장 프로그램을 시작하기 전에 자동화 할 수 있는지/일반화 할 수 있는지에 대해 ... Zip에 대해 설명해 주시겠습니까? SelectMany (from +에서)와 병합 할 때도 사용할 수 있습니까? – TDaver

+0

@TDaver -'Zip'은 지퍼와 같습니다. - {a, b, c} .Zip {1, 2, 3} -> {a1, b2, c3}의 쌍으로 값과 일치하는 두 개의 관측 값을 결합합니다. 'SelectMany'는 필수적으로 하나의 관찰 결과를 두 번째 생성으로 연결 한 다음 결과의 평평한 목록을 반환하는 데 사용됩니다. flattens'IO >을'IO '에 병합하십시오. – Enigmativity

+0

@TDaver : 중요한 연산자를 더 잘 이해하려면 "심층"MSDN 시리즈를 확인하십시오. 대부분의 동영상은 몇 분 밖에 걸리지 않으며 Zip, SelectMany 등과 같은 것들을 포함합니다. http://channel9.msdn.com/search?term=%22Reactive+Extensions+API+in+depth%22&type=Blogs –

관련 문제