using System; using System.Windows; using System.Windows.Threading; using Caliburn.Execution; using Caliburn.Messaging; using Caliburn.Metadata; namespace Caliburn.Actions { public class AsynchronousActionExecutor : ActionExecutor { private IUnboundMethod _callbackMethod; public AsynchronousActionExecutor(ActionInfo actionInfo) : base(actionInfo) {} public bool HasCallback { get { return _callbackMethod != null; } } public override void Execute(DependencyObject messageSource, ActionMessage message, object target) { object[] parameters = DetermineParameters(message, messageSource); _unboundMethod.AsyncExecute( target, ExecutionCallback, new AsynchronousInfo(messageSource, message, target), parameters ); } protected virtual void ExecutionCallback(IAsyncResult asyncResult) { UnboundAsyncState state = (UnboundAsyncState) asyncResult.AsyncState; AsynchronousInfo info = (AsynchronousInfo) state.OriginalState; Action action = delegate { if(state.Exception == null) { try { BindReturnValue(info.Message, info.MessageSource, state.ReturnValue); if (HasCallback) _callbackMethod.Execute(info.Target); } catch(Exception e) { PerformRescue(info.Target, e.InnerException ?? e); } } else PerformRescue(info.Target, state.Exception); }; info.MessageSource.Dispatcher.Invoke(DispatcherPriority.Normal, action); } public virtual void InitializeCallback(Type declaringType, string callback) { _callbackMethod = UnboundMethodFactory.Create( declaringType.GetMethod(callback) ); } } }