public override object Execute(ControllerContext controllerContext, IDictionary <string, object> parameters) { if (controllerContext == null) { throw new ArgumentNullException("controllerContext"); } if (parameters == null) { throw new ArgumentNullException("parameters"); } // Performance sensitive so avoid Linq or delegates. ParameterInfo[] parameterInfos = MethodInfo.GetParameters(); object[] parametersArray = new object[parameterInfos.Length]; for (int i = 0; i < parameterInfos.Length; i++) { ParameterInfo parameterInfo = parameterInfos[i]; object parameter = ExtractParameterFromDictionary(parameterInfo, parameters, MethodInfo); parametersArray[i] = parameter; } ActionMethodDispatcher dispatcher = DispatcherCache.GetDispatcher(MethodInfo); object actionReturnValue = dispatcher.Execute(controllerContext.Controller, parametersArray); return(actionReturnValue); }
public override IAsyncResult BeginExecute(ControllerContext controllerContext, IDictionary <string, object> parameters, AsyncCallback callback, object state) { if (controllerContext == null) { throw new ArgumentNullException("controllerContext"); } if (parameters == null) { throw new ArgumentNullException("parameters"); } AsyncManager asyncManager = GetAsyncManager(controllerContext.Controller); BeginInvokeDelegate beginDelegate = delegate(AsyncCallback asyncCallback, object asyncState) { // call the XxxAsync() method ParameterInfo[] parameterInfos = AsyncMethodInfo.GetParameters(); var rawParameterValues = from parameterInfo in parameterInfos select ExtractParameterFromDictionary(parameterInfo, parameters, AsyncMethodInfo); object[] parametersArray = rawParameterValues.ToArray(); TriggerListener listener = new TriggerListener(); SimpleAsyncResult asyncResult = new SimpleAsyncResult(asyncState); // hook the Finished event to notify us upon completion Trigger finishTrigger = listener.CreateTrigger(); asyncManager.Finished += delegate { finishTrigger.Fire(); }; asyncManager.OutstandingOperations.Increment(); // to simplify the logic, force the rest of the pipeline to execute in an asynchronous callback listener.SetContinuation(() => ThreadPool.QueueUserWorkItem(_ => asyncResult.MarkCompleted(false /* completedSynchronously */, asyncCallback))); // the inner operation might complete synchronously, so all setup work has to be done before this point ActionMethodDispatcher dispatcher = DispatcherCache.GetDispatcher(AsyncMethodInfo); dispatcher.Execute(controllerContext.Controller, parametersArray); // ignore return value from this method // now that the XxxAsync() method has completed, kick off any pending operations asyncManager.OutstandingOperations.Decrement(); listener.Activate(); return(asyncResult); }; EndInvokeDelegate <object> endDelegate = delegate(IAsyncResult asyncResult) { // call the XxxCompleted() method ParameterInfo[] completionParametersInfos = CompletedMethodInfo.GetParameters(); var rawCompletionParameterValues = from parameterInfo in completionParametersInfos select ExtractParameterOrDefaultFromDictionary(parameterInfo, asyncManager.Parameters); object[] completionParametersArray = rawCompletionParameterValues.ToArray(); ActionMethodDispatcher dispatcher = DispatcherCache.GetDispatcher(CompletedMethodInfo); object actionReturnValue = dispatcher.Execute(controllerContext.Controller, completionParametersArray); return(actionReturnValue); }; return(AsyncResultWrapper.Begin(callback, state, beginDelegate, endDelegate, _executeTag, asyncManager.Timeout)); }
public void Can_Get_Cached_Dispatcher_By_Method() { Dispatcher d1 = Dispatcher.For(typeof(A), m1); Dispatcher d2 = Dispatcher.For(typeof(A), m2); Assert.AreNotSame(d1, d2); Assert.AreSame(d1, DispatcherCache.ForType(typeof(A)).DispatcherFor(m1)); Assert.AreSame(d2, DispatcherCache.ForType(typeof(A)).DispatcherFor(m2)); }
public void Setup() { DispatcherCache.Clear(); circle = new Circle(); rect = new Rectangle(); roundedRect = new RoundedRectangle(); morph = new Morph(); ellipse = new Ellipse(); }
public override object Execute(ControllerContext context, IDictionary <string, object> parameters) { Precondition.Require(context, () => Error.ArgumentNull("context")); Precondition.Require(parameters, () => Error.ArgumentNull("parameters")); object[] parameterValues = _method.GetParameters() .Select(p => ExtractParameter(p, parameters, _method)) .ToArray(); return(DispatcherCache.GetDispatcher(_method).Execute(context.Controller, parameterValues)); }
public void Can_Get_Cache_For_Type() { DispatcherCache a = DispatcherCache.ForType(typeof(A)); DispatcherCache b = DispatcherCache.ForType(typeof(B)); Assert.IsNotNull(a); Assert.IsNotNull(b); Assert.AreSame(a, DispatcherCache.ForType(typeof(A))); Assert.AreSame(b, DispatcherCache.ForType(typeof(B))); }
public override IAsyncResult BeginExecute(ControllerContext context, IDictionary <string, object> parameters, AsyncCallback callback, object state) { Precondition.Require(context, () => Error.ArgumentNull("context")); Precondition.Require(parameters, () => Error.ArgumentNull("parameters")); AsyncManager asyncManager = GetAsyncManager(context.Controller); BeginInvokeDelegate beginDelegate = delegate(AsyncCallback asyncCallback, object asyncState) { object[] parameterValues = _entryMethod.GetParameters() .Select(p => ExtractParameter(p, parameters, _entryMethod)) .ToArray(); TriggerListener listener = new TriggerListener(); MvcAsyncResult asyncResult = new MvcAsyncResult(asyncState); Trigger finishTrigger = listener.CreateTrigger(); asyncManager.Finished += delegate { finishTrigger.Fire(); }; asyncManager.OutstandingOperations.Increment(); listener.SetContinuation(() => ThreadPool.QueueUserWorkItem(_ => asyncResult.MarkCompleted(false, asyncCallback))); DispatcherCache.GetDispatcher(_entryMethod) .Execute(context.Controller, parameterValues); asyncManager.OutstandingOperations.Decrement(); listener.Activate(); return(asyncResult); }; EndInvokeDelegate <object> endDelegate = delegate(IAsyncResult asyncResult) { object[] parameterValues = _completedMethod.GetParameters() .Select(p => ExtractParameter(p, parameters, _completedMethod)) .ToArray(); return(DispatcherCache.GetDispatcher(_completedMethod) .Execute(context.Controller, parameterValues)); }; return(AsyncResultWrapper.Begin(callback, state, beginDelegate, endDelegate, _executeTag, asyncManager.Timeout)); }
public override IAsyncResult BeginExecute(ControllerContext controllerContext, IDictionary <string, object> parameters, AsyncCallback callback, object state) { if (controllerContext == null) { throw new ArgumentNullException("controllerContext"); } if (parameters == null) { throw new ArgumentNullException("parameters"); } ParameterInfo[] parameterInfos = BeginMethod.GetParameters(); IEnumerable <object> rawParameterValues = from parameterInfo in parameterInfos select ExtractParameterFromDictionary(parameterInfo, parameters, BeginMethod); List <object> parametersList = rawParameterValues.Take(parameterInfos.Length - 2).ToList(); MethodDispatcher beginDispatcher = DispatcherCache.GetDispatcher(BeginMethod); MethodDispatcher endDispatcher = DispatcherCache.GetDispatcher(EndMethod); // need to add callback + state object to list BeginInvokeCallback beginCallback = (innerCallback, innerState) => { parametersList.Add(innerCallback); parametersList.Add(innerState); object[] parametersArray = parametersList.ToArray(); IAsyncResult innerAsyncResult = (IAsyncResult)beginDispatcher.Execute(controllerContext.Controller, parametersArray); return(innerAsyncResult); }; AsyncCallback <object> endCallback = ar => { object actionReturnValue = endDispatcher.Execute(controllerContext.Controller, new object[] { ar }); return(actionReturnValue); }; // Set the timeout and go IAsyncManagerContainer helperContainer = controllerContext.Controller as IAsyncManagerContainer; int timeout = (helperContainer != null) ? helperContainer.AsyncManager.Timeout : Timeout.Infinite; return(AsyncResultWrapper.WrapWithTimeout(callback, state, beginCallback, endCallback, timeout, _executeTag)); }
public override object Execute(ControllerContext controllerContext, IDictionary <string, object> parameters) { if (controllerContext == null) { throw new ArgumentNullException("controllerContext"); } if (parameters == null) { throw new ArgumentNullException("parameters"); } ParameterInfo[] parameterInfos = MethodInfo.GetParameters(); var rawParameterValues = from parameterInfo in parameterInfos select ExtractParameterFromDictionary(parameterInfo, parameters, MethodInfo); object[] parametersArray = rawParameterValues.ToArray(); ActionMethodDispatcher dispatcher = DispatcherCache.GetDispatcher(MethodInfo); object actionReturnValue = dispatcher.Execute(controllerContext.Controller, parametersArray); return(actionReturnValue); }
public override IAsyncResult BeginExecute(ControllerContext controllerContext, IDictionary <string, object> parameters, AsyncCallback callback, object state) { if (controllerContext == null) { throw new ArgumentNullException("controllerContext"); } if (parameters == null) { throw new ArgumentNullException("parameters"); } ParameterInfo[] parameterInfos = TaskMethodInfo.GetParameters(); var rawParameterValues = from parameterInfo in parameterInfos select ExtractParameterFromDictionary(parameterInfo, parameters, TaskMethodInfo); object[] parametersArray = rawParameterValues.ToArray(); CancellationTokenSource tokenSource = null; bool disposedTimer = false; Timer taskCancelledTimer = null; bool taskCancelledTimerRequired = false; int timeout = GetAsyncManager(controllerContext.Controller).Timeout; for (int i = 0; i < parametersArray.Length; i++) { if (default(CancellationToken).Equals(parametersArray[i])) { tokenSource = new CancellationTokenSource(); parametersArray[i] = tokenSource.Token; // If there is a timeout we will create a timer to cancel the task when the // timeout expires. taskCancelledTimerRequired = timeout > Timeout.Infinite; break; } } ActionMethodDispatcher dispatcher = DispatcherCache.GetDispatcher(TaskMethodInfo); if (taskCancelledTimerRequired) { taskCancelledTimer = new Timer(_ => { lock (tokenSource) { if (!disposedTimer) { tokenSource.Cancel(); } } }, state: null, dueTime: timeout, period: Timeout.Infinite); } Task taskUser = dispatcher.Execute(controllerContext.Controller, parametersArray) as Task; Action cleanupAtEndExecute = () => { // Cleanup code that's run in EndExecute, after we've waited on the task value. if (taskCancelledTimer != null) { // Timer callback may still fire after Dispose is called. taskCancelledTimer.Dispose(); } if (tokenSource != null) { lock (tokenSource) { disposedTimer = true; tokenSource.Dispose(); if (tokenSource.IsCancellationRequested) { // Give Timeout exceptions higher priority over other exceptions, mainly OperationCancelled exceptions // that were signaled with out timeout token. throw new TimeoutException(); } } } }; TaskWrapperAsyncResult result = new TaskWrapperAsyncResult(taskUser, state, cleanupAtEndExecute); // if user supplied a callback, invoke that when their task has finished running. if (callback != null) { if (taskUser.IsCompleted) { // If the underlying task is already finished, from our caller's perspective this is just // a synchronous completion. result.CompletedSynchronously = true; callback(result); } else { // If the underlying task isn't yet finished, from our caller's perspective this will be // an asynchronous completion. We'll use ContinueWith instead of Finally for two reasons: // // - Finally propagates the antecedent Task's exception, which we don't need to do here. // Out caller will eventually call EndExecute, which correctly observes the // antecedent Task's exception anyway if it faulted. // // - Finally invokes the callback on the captured SynchronizationContext, which is // unnecessary when using APM (Begin / End). APM assumes that the callback is invoked // on an arbitrary ThreadPool thread with no SynchronizationContext set up, so // ContinueWith gets us closer to the desired semantic. result.CompletedSynchronously = false; taskUser.ContinueWith(_ => { callback(result); }); } } return(result); }
public override IAsyncResult BeginExecute(ControllerContext controllerContext, IDictionary <string, object> parameters, AsyncCallback callback, object state) { if (controllerContext == null) { throw new ArgumentNullException("controllerContext"); } if (parameters == null) { throw new ArgumentNullException("parameters"); } ParameterInfo[] parameterInfos = TaskMethodInfo.GetParameters(); var rawParameterValues = from parameterInfo in parameterInfos select ExtractParameterFromDictionary(parameterInfo, parameters, TaskMethodInfo); object[] parametersArray = rawParameterValues.ToArray(); CancellationTokenSource tokenSource = null; bool disposedTimer = false; Timer taskCancelledTimer = null; bool taskCancelledTimerRequired = false; int timeout = GetAsyncManager(controllerContext.Controller).Timeout; for (int i = 0; i < parametersArray.Length; i++) { if (default(CancellationToken).Equals(parametersArray[i])) { tokenSource = new CancellationTokenSource(); parametersArray[i] = tokenSource.Token; // If there is a timeout we will create a timer to cancel the task when the // timeout expires. taskCancelledTimerRequired = timeout > Timeout.Infinite; break; } } ActionMethodDispatcher dispatcher = DispatcherCache.GetDispatcher(TaskMethodInfo); if (taskCancelledTimerRequired) { taskCancelledTimer = new Timer(_ => { lock (tokenSource) { if (!disposedTimer) { tokenSource.Cancel(); } } }, state: null, dueTime: timeout, period: Timeout.Infinite); } Task taskUser = dispatcher.Execute(controllerContext.Controller, parametersArray) as Task; Action cleanupAtEndExecute = () => { // Cleanup code that's run in EndExecute, after we've waited on the task value. if (taskCancelledTimer != null) { // Timer callback may still fire after Dispose is called. taskCancelledTimer.Dispose(); } if (tokenSource != null) { lock (tokenSource) { disposedTimer = true; tokenSource.Dispose(); if (tokenSource.IsCancellationRequested) { // Give Timeout exceptions higher priority over other exceptions, mainly OperationCancelled exceptions // that were signaled with out timeout token. throw new TimeoutException(); } } } }; TaskWrapperAsyncResult result = new TaskWrapperAsyncResult(taskUser, state, cleanupAtEndExecute); // if user supplied a callback, invoke that when their task has finished running. if (callback != null) { taskUser.Finally(() => { callback(result); }); } return(result); }
private static Dispatcher GetDispatcher(object target, string cacheKeyName, Type[] cacheKeyTypes, DispatcherCache.DispatcherFactory factory) { var targetType = (target as Type) ?? target.GetType(); var key = new DispatcherKey(targetType, cacheKeyName, cacheKeyTypes); return _cache.Get(key, factory); }
private static Dispatcher GetDispatcher(object target, object[] args, string cacheKeyName, DispatcherCache.DispatcherFactory factory) { var cacheKeyTypes = MethodResolver.GetArgumentTypes(args); return GetDispatcher(target, cacheKeyName, cacheKeyTypes, factory); }
public void Using_MultiMethod_Will_Add_To_DispatcherCache() { // Shape constructor: MultiMethod.Func<IShape, string>(this.Intersect) Assert.Greater(DispatcherCache.ForType(typeof(Circle)).Size, 0); }
public override IAsyncResult BeginExecute(ControllerContext controllerContext, IDictionary <string, object> parameters, AsyncCallback callback, object state) { if (controllerContext == null) { throw new ArgumentNullException("controllerContext"); } if (parameters == null) { throw new ArgumentNullException("parameters"); } AsyncManager asyncHelper = GetAsyncManager(controllerContext.Controller); SingleFireEvent setupCompletedEvent = new SingleFireEvent(); BeginInvokeCallback beginCallback = (innerCallback, innerState) => { ManualAsyncResult asyncResult = new ManualAsyncResult() { AsyncState = innerState }; // Get parameters for async setup method, then execute ParameterInfo[] setupParametersInfos = SetupMethod.GetParameters(); var rawSetupParameterValues = from parameterInfo in setupParametersInfos select ExtractParameterFromDictionary(parameterInfo, parameters, SetupMethod); object[] setupParametersArray = rawSetupParameterValues.ToArray(); // to simplify the logic, force an asynchronous callback asyncHelper.OutstandingOperations.Completed += delegate { if (setupCompletedEvent.Signal()) { ThreadPool.QueueUserWorkItem(o => { asyncResult.MarkCompleted(false /* completedSynchronously */, innerCallback); }); } }; MethodDispatcher setupDispatcher = DispatcherCache.GetDispatcher(SetupMethod); asyncHelper.OutstandingOperations.Increment(); setupDispatcher.Execute(controllerContext.Controller, setupParametersArray); asyncHelper.OutstandingOperations.Decrement(); return(asyncResult); }; AsyncCallback <object> endCallback = ar => { if (setupCompletedEvent.Signal()) { // the setup method did not complete before this callback executed throw new InvalidOperationException(MvcResources.AsyncActionDescriptor_EndExecuteCalledPrematurely); } // Get parameters for action method, then execute ParameterInfo[] completionParametersInfos = CompletionMethod.GetParameters(); var rawCompletionParameterValues = from parameterInfo in completionParametersInfos select ExtractParameterOrDefaultFromDictionary(parameterInfo, asyncHelper.Parameters); object[] completionParametersArray = rawCompletionParameterValues.ToArray(); MethodDispatcher completionDispatcher = DispatcherCache.GetDispatcher(CompletionMethod); object actionReturnValue = completionDispatcher.Execute(controllerContext.Controller, completionParametersArray); return(actionReturnValue); }; // Set the timeout and go int timeout = asyncHelper.Timeout; return(AsyncResultWrapper.WrapWithTimeout(callback, state, beginCallback, endCallback, timeout, _executeTag)); }
public void Setup() { DispatcherCache.Clear(); }