Posts Tagged ‘Wcf

23
Oct
10

A quick Caliburn.Micro tip: WebService result

UPDATE 2011/01/03

Fixed a couple bugs:

  • Missing exception handling on callback execution
  • Missing null check on Message property

Many thanks to Luca D’Angelo for pointing them out.



A user recently asked, on Caliburn.Micro forum, for an equivalent version of WebServiceResult, a convenience IResult built by Rob in the (full) Caliburn’s Contact Manager sample.

Porting was quite straightforward, despite the important difference in the framework internal structure.

Here is the class source:

 
using System; 
using System.Linq; 
using System.Linq.Expressions; 
public class WebServiceResult<T, K> : IResult 
	where T : new() 
	where K : EventArgs< 
{
	readonly static Func<bool> ALWAYS_FALSE_GUARD= () => false;
	readonly static Func<bool> ALWAYS_TRUE_GUARD = () => true;
	private readonly Action<K> _callback;
	private readonly Expression<Action<T>> _serviceCall;
	private ActionExecutionContext _currentContext;
	private Func<bool> _originalGuard;
	public WebServiceResult(Expression<Action<T>> serviceCall)
	{
		_serviceCall = serviceCall;
	}
	public WebServiceResult(Expression<Action<T>> serviceCall, Action<K> callback)
	{
		_serviceCall = serviceCall;
		_callback = callback;
	}
	public event EventHandler<ResultCompletionEventArgs> Completed = delegate { };
	public void Execute(ActionExecutionContext context)
	{
		_currentContext = context;
		//if you would to disable the control that caused the service to be called, you could do this:
		ChangeAvailability(false);
		var lambda = (LambdaExpression)_serviceCall;
		var methodCall = (MethodCallExpression)lambda.Body;
		var eventName = methodCall.Method.Name.Replace("Async", "Completed");
		var eventInfo = typeof(T).GetEvent(eventName);
		var service = new T();
		eventInfo.AddEventHandler(service, new EventHandler<K>(OnEvent));
		_serviceCall.Compile()(service);
	}
	public void OnEvent(object sender, K args)
	{
		//re-enable the control that caused the service to be called:
		ChangeAvailability(true);
                try {
		    if (_callback != null)
			_callback(args);
	    	    Completed(this, new ResultCompletionEventArgs());
                } catch (Exception ex) {
	    	    Completed(this, new ResultCompletionEventArgs{ Error = ex });
                }
	}
	private void ChangeAvailability(bool isAvailable)
	{
		if (_currentContext == null || _currentContext.Message == null) return;
		if (!isAvailable) {
			_originalGuard = _currentContext.CanExecute;
			_currentContext.CanExecute = ALWAYS_FALSE_GUARD;
		}
		else if (_currentContext.CanExecute == ALWAYS_FALSE_GUARD) {
			_currentContext.CanExecute = _originalGuard ?? ALWAYS_TRUE_GUARD;
		}
		_currentContext.Message.UpdateAvailability();
	}
}

The invocation:

//in the service code
public class MyService
{
	[OperationContract]
	public int DoWork(int value)
	{
		return new Random().Next();
	}
}
//in the calling ViewModel code
public IEnumerable<IResult> CallService()
{
	int theParameter = 0;
	yield return new WebServiceResult<MyServiceClient, DoWorkCompletedEventArgs>(
		x => x.DoWorkAsync(theParameter),
		x => UseResultElsewhere(x.Result)
	);
}



June 2017
S M T W T F S
« Oct    
 123
45678910
11121314151617
18192021222324
252627282930  

%d bloggers like this: