private MethodInfo GetAvailabilityMethod(string?availabilityMethodName) { if (availabilityMethodName == null) { throw new Exception("If the action is conditionally available you need to provide a method to calculate availability."); } var declaringType = ActionMethod.DeclaringType; var method = declaringType.GetMethod(availabilityMethodName); if (method == null) { throw new Exception($"Availability Method {availabilityMethodName} was not found on type {declaringType.FullName}"); } if (method.ReturnType != typeof(bool)) { throw new Exception($"AvailabilityCheck method ({availabilityMethodName}) MUST return bool."); } var actionBindingParameterType = ActionMethod.GetParameters().First().ParameterType; var methodParameters = method.GetParameters(); if (methodParameters.Count() != 1 || methodParameters.First().ParameterType != actionBindingParameterType) { throw new Exception($"AvailabilityCheck method was expected to have this signature 'bool {availabilityMethodName}({actionBindingParameterType.FullName})'"); } return(method); }
private static object[] CreateActionArguments(CliActionContext context) { var parameters = context.ActionRoute !.ActionMethod.GetParameters(); switch (parameters.Length) { case 0: return(Array.Empty <object>()); case > 1: throw new TargetParameterCountException("Action argument count must be 0 or 1"); default: { var option = new OptionParser(parameters.First().ParameterType).Parse(context.Arguments.ToArray()); return(new[] { option }); } } }
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(); ContinuationListener listener = new ContinuationListener(); object theDelegate = null; BeginInvokeCallback beginCallback = (innerCallback, innerState) => { ManualAsyncResult asyncResult = new ManualAsyncResult() { AsyncState = innerState }; // Get parameters for async setup method, then execute ParameterInfo[] setupParametersInfos = ActionMethod.GetParameters(); var rawSetupParameterValues = from parameterInfo in setupParametersInfos select ExtractParameterFromDictionary(parameterInfo, parameters, ActionMethod); object[] setupParametersArray = rawSetupParameterValues.ToArray(); // to simplify the logic, force an asynchronous callback asyncHelper.OutstandingOperations.Completed += delegate { if (setupCompletedEvent.Signal()) { listener.SetContinuation(() => { ThreadPool.QueueUserWorkItem(o => { asyncResult.MarkCompleted(false /* completedSynchronously */, innerCallback); }); }); } }; MethodDispatcher setupDispatcher = DispatcherCache.GetDispatcher(ActionMethod); asyncHelper.OutstandingOperations.Increment(); object returnedDelegate = setupDispatcher.Execute(controllerContext.Controller, setupParametersArray); ValidateDelegateNotNull(returnedDelegate, ActionMethod); asyncHelper.OutstandingOperations.Decrement(); Thread.VolatileWrite(ref theDelegate, returnedDelegate); listener.Signal(); 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); } object returnedDelegate = Thread.VolatileRead(ref theDelegate); MethodInfo invokeMethod = returnedDelegate.GetType().GetMethod("Invoke", Type.EmptyTypes); MethodDispatcher invokeDispatcher = DispatcherCache.GetDispatcher(invokeMethod); object actionReturnValue = invokeDispatcher.Execute(returnedDelegate, _emptyParameters); return(actionReturnValue); }; // Set the timeout and go int timeout = asyncHelper.Timeout; return(AsyncResultWrapper.WrapWithTimeout(callback, state, beginCallback, endCallback, timeout, _executeTag)); }