i have a question using Observables in Silverlight 4 to make WCF calls. Consider the simple webservice call below.
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
});
i have implemented an extension method, that wraps the subscribe method, it does some error validation on the return.
On the return results.Subscribe(e =>
e is System.Collections.Generic.Event<AuthorizeAdministratorCompletedEventArgs>
almost every query will have a different return type such as:
e is System.Collections.Generic.Event<AsyncCompletedEventArgs>
if i had a wrapper that looked something like this, how can i cast every type 开发者_开发知识库of xxxCompletedEventArgs to its base type AsyncCompletedEventArgs so that i can access e.EventArgs and inspect the Error property
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; });
}
The code above will fail
Unable to cast object of type 'System.Collections.Generic.Event
1[MyProject.Provider.AuthorizeAdministratorCompletedEventArgs]' to type 'System.Collections.Generic.IEvent1[System.ComponentModel.AsyncCompletedEventArgs]'
This is the method definition of WCFExceptionHandler.HandleError(args.EventArgs))
public static bool HandleError(AsyncCompletedEventArgs e)
I'd probably change you extension method so that it acts to handle the the events as a non blocking operator (much the same as the majority of the Rx extension method operators). Something like:
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);
});
}
Then call it through:
results.GetHandledEvents()
.Finally(() => DoSomethingFinally())
.Subscribe(e =>
{
//Enable UI Button
},
ex => HandleException(ex),
() => HandleComplete());
I think this should solve your issues as the events will funnel through as their original type and it ensures that HandleError
gets event args that are the correct type.
精彩评论