silverlight, используя Observables для вызовов WCF, приведя IEvent <T>, где T: AsyncCompletedEventArgs - PullRequest
1 голос
/ 23 февраля 2011

У меня есть вопрос, используя Observables в Silverlight 4 для выполнения вызовов WCF. Рассмотрим простой вызов веб-службы ниже.

var adminclient = ServiceProxy.WithFactory<AuthenticationClient>();
var results= Observable.FromEvent<AuthorizeAdministratorCompletedEventArgs>(
   s => adminclient.AuthorizeAdministratorCompleted += s,
   s => adminclient.AuthorizeAdministratorCompleted -= s).ObserveOnDispatcher();

adminclient.AuthorizeAdministratorAsync();
results.Subscribe(e =>
{
   //Enable UI Button
});

Я реализовал метод расширения, который обертывает метод подписки, он выполняет некоторую проверку ошибок при возврате.


На возврат Результаты. Подписка (e =>

e is System.Collections.Generic.Event<AuthorizeAdministratorCompletedEventArgs>

почти каждый запрос будет иметь другой тип возврата, такой как:

e is System.Collections.Generic.Event<AsyncCompletedEventArgs>

если бы у меня была оболочка, которая выглядела примерно так, как я могу привести каждый тип xxxCompletedEventArgs к его базовому типу AsyncCompletedEventArgs , чтобы я мог получить доступ к e.EventArgs и проверьте Ошибка свойство

public static IDisposable Subscribe<TSource>(this IObservable<TSource> source, Action<TSource> onNext = null, Action onError = null, Action onFinal = null)
{
    Action<TSource> onNextWrapper = (s) =>
    {                   
    var args = (System.Collections.Generic.IEvent<AsyncCompletedEventArgs>)s;

    try
       {                            
          if (WCFExceptionHandler.HandleError(args.EventArgs))
             {
                if (onNext != null)
                   onNext(s);
             }
             else
             {
                if (onError != null)
                   onError();
             }
        }
        finally
        {
           if (onFinal != null)
              onFinal();
        }
   };

   return source.Subscribe<TSource>(onNextWrapper, (e) => { throw e; });
}

Приведенный выше код не будет работать

Невозможно привести объект типа 'System.Collections.Generic.Event 1 [MyProject.Provider.AuthorizeAdministratorCompletedEventArgs] 'для ввода' System.Collections.Generic.IEvent 1[System.ComponentModel.AsyncCompletedEventArgs]'

Это определение метода WCFExceptionHandler.HandleError (args.EventArgs))

public static bool HandleError(AsyncCompletedEventArgs e)

1 Ответ

3 голосов
/ 23 февраля 2011

Я бы, вероятно, изменил ваш метод расширения так, чтобы он действовал для обработки событий как неблокирующий оператор (почти такой же, как большинство операторов метода расширения Rx). Что-то вроде:

public static IObservable<IEvent<TEventArgs>> GetHandledEvents<TEventArgs>(this IObservable<IEvent<TEventArgs>> source)
    where TEventArgs : AsyncCompletedEventArgs
{
    return Observable.CreateWithDisposable<IEvent<TEventArgs>>(observer =>
        {
            return source.Subscribe(evt =>
                {
                    try
                    {
                        if (WCFExceptionHandler.HandleError(evt.EventArgs))
                        {
                            observer.OnNext(evt);
                        }
                        else
                        {
                            observer.OnError(new Exception("Some Exception"));
                        }
                    }
                    finally
                    {
                        observer.OnError(new Exception("Some Other Exception"));
                    }
                }, 
                observer.OnError, 
                observer.OnCompleted);
        });
}

Тогда позвоните через:

results.GetHandledEvents()
  .Finally(() => DoSomethingFinally())
  .Subscribe(e =>
  {
   //Enable UI Button
  },
  ex => HandleException(ex),
  () => HandleComplete());

Я думаю это должно решить ваши проблемы, так как события будут проходить как их первоначальный тип, и это гарантирует, что HandleError получит аргументы событий, которые имеют правильный тип.

...